package com.xbongbong.sys.model.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.TypeReference;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.dao.PaasAppDao;
import com.xbongbong.paas.domain.dao.PaasFormDao;
import com.xbongbong.paas.domain.dao.PaasMenuDao;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.vo.UserFormPermissionVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.pojo.AppPermissionPojo;
import com.xbongbong.paas.toolbox.pojo.DataPermissionParamsPojo;
import com.xbongbong.paas.toolbox.pojo.ModulePermissionPojo;
import com.xbongbong.paas.toolbox.pojo.PermissionTermsPojo;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PinyinUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.DepartmentVO;
import com.xbongbong.paas.toolbox.wrap.RoleSimpleVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.SystemAppMenuEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.sys.domain.dao.UserDao;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.ProPermissionEntity;
import com.xbongbong.sys.domain.entity.RoleEntity;
import com.xbongbong.sys.domain.entity.UserDepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.domain.entity.WeakManageEntity;
import com.xbongbong.sys.domain.entity.ext.UserEntityExt;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.help.SysCloudCodeHelp;
import com.xbongbong.sys.help.SysProPermissionHelp;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.ProPermissionModel;
import com.xbongbong.sys.model.RoleModel;
import com.xbongbong.sys.model.UserDepartmentModel;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.sys.model.WeakManageModel;
import com.xbongbong.sys.pojo.DataPermissionDetailPojo;
import com.xbongbong.sys.pojo.DataPermissionsPojo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author kaka
 * @date 2018-8-28 14:23
 */
@Service("userModel")
public class UserModelImpl implements UserModel {

    private static final Logger LOG = LoggerFactory.getLogger(UserModelImpl.class);

    private static final Object LIST_COLUMNS = "id, corpid, user_id, role_ids, mobile, name,active,is_admin,is_boss,ding_id,position,avatar,jobnumber, department, order_in_depts, is_leader_in_depts,extattr,is_visible, add_time, update_time, del, is_push_message, passport_id ,email ,qr_code,labels ";

    private static final Object PINYIN_COLUMNS = "id, corpid, user_id, role_ids, mobile, name,active,is_admin,is_boss,ding_id,position,avatar,jobnumber, department, order_in_depts, is_leader_in_depts,extattr,is_visible, add_time, update_time, del, is_push_message, passport_id, " + PinyinUtil.formatFirstPinyinStr("name") + " as firstPinyin";

    private static final Object LEAVE_MARKS_COLUMS = "case del when 1 then concat(name,\"(离职)\") when 0 then name end as name";

    private static final Object LIST_LEAVE_MARKS_COLUMS = "id, corpid, user_id, role_ids, mobile,active,is_admin,is_boss,ding_id,position,avatar,jobnumber, department, order_in_depts, is_leader_in_depts,extattr,is_visible, add_time, update_time, del, is_push_message, passport_id, case del when 1 then concat(name,\"(离职)\") when 0 then name end as name";

    @Resource
    private UserDao userDao;
    /**
     * 本处是一处规范破例，此处逻辑耦合度较高，涉及一些底层方法调用
     */
    @Resource
    private RoleModel roleModel;
    @Resource
    private UserDepartmentModel userDepartmentModel;
    @Resource
    private WeakManageModel weakManageModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private ProPermissionModel proPermissionModel;
    @Resource
    private PaasFormDao paasFormDao;
    @Resource
    private PaasAppDao paasAppDao;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PaasMenuDao paasMenuDao;
    @Resource
    private SysCloudCodeHelp sysCloudCodeHelp;

    @Override
    public UserEntity getByKey(String key, String corpid) {
        return userDao.getByKey(key, corpid, 0);
    }

    @Override
    public UserEntity getByKey(String key, String corpid, Integer del) {
        return userDao.getByKey(key, corpid, del);
    }

    @Override
    public Integer roleBathDel(String corpid, List<String> userIds, Integer roleId) {
        return userDao.roleBatchDel(corpid, userIds, roleId);
    }

    @Override
    public Integer roleBathAdd(String corpid, List<String> userIds, Integer roleId) {
        return userDao.roleBatchAdd(corpid, userIds, roleId);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return userDao.getEntitysCount(param);
    }

    @Override
    public List findEntitysWithoutSub(Map<String, Object> param) {
        return null;
    }

    @Override
    public Integer insert(UserEntity entity) {
        Integer now = DateUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        return userDao.insert(entity);
    }

    @Override
    public Integer update(UserEntity entity) {
        Integer now = DateUtil.getInt();
        entity.setUpdateTime(now);
        return userDao.update(entity);
    }
    @Override
    public List<UserEntity> findEntitys(Map<String, Object> param) {
        if(Objects.equals(param.get(ParameterConstant.COLUMNS),null)){
            param.put(ParameterConstant.COLUMNS, LIST_COLUMNS);
        }
        /**
         * 是否需要有离职标记，0:不需要，1:需要
         */
        if ( Objects.equals(param.get(ParameterConstant.LEAVE_MARKS),BasicConstant.ONE) ) {
            param.remove(ParameterConstant.LEAVE_MARKS);
            param.put("orderByStr", "del asc");
            if(Objects.equals(param.get(ParameterConstant.COLUMNS),null)){
                param.put(ParameterConstant.COLUMNS, LIST_LEAVE_MARKS_COLUMS);
            } else {
                String columns = param.get(ParameterConstant.COLUMNS).toString().replace("name", (CharSequence) LEAVE_MARKS_COLUMS);
                if ( Objects.nonNull(columns) ) {
                    param.put(ParameterConstant.COLUMNS, columns);
                }
            }
        }
        return userDao.findEntitys(param);
    }

    @Override
    public List<UserEntity> findEntitysByUserIds(List<String> userIdsList, String corpid) {
        return userDao.findEntitysByUserIds(userIdsList, corpid);
    }

    @Override
    public List<String> getUserIds(Map<String ,Object>  param){
        return userDao.getUserIds(param);
    }

    @Override
    public List<String> getUserIdsJoin(Map<String ,Object>  param){
        return userDao.getUserIdsJoin(param);
    }

    /**
     * 获取某个员工的下属员工列表(userId列表),可选择排除或不排除自己
     * @param userEntity 需要获取下属员工userId列表的员工
     * @param ifAdminViewAll 管理员是否可以查看公司所有下属；
     *                       ifAdminViewAll=false管理员只能看下属；ifAdminViewAll=true 能看到所有
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工、且包含隐藏员工
     * @param excludeOneSelf 是否排除自己，true 则排除自己，false不排除
     * @return 返回下属员工 userId 列表
     * @author cp.zhang
     * @author kaka
     * @date 2017-3-3 下午5:03:51
     */
    @Override
    public List<String> getSubIdList(UserEntity userEntity, boolean ifAdminViewAll, int viewPermission,
                                     boolean excludeOneSelf) throws IllegalArgumentException {

        List<String> subIdList;
        if(userEntity == null){
            throw new IllegalArgumentException("userEntity 不能为 NULL");
        }

        if(ifAdminViewAll && userEntity.isOriAdmin()){
            //老板，获取所有员工list
            if(userEntity.getCorpid() == null){
                throw new IllegalArgumentException("userEntity corpid 不能为 NULL");
            }
            Map<String,Object> param = new HashMap<>(8);
            param.put("corpid", userEntity.getCorpid());
            //viewPermission = 1，则包含离职员工、且包含隐藏员工
            if (viewPermission != 1) {
                param.put("del", 0);
            }
            param.put("start", 0);
            param.put("pageNum", BasicConstant.MAX_USER_COUNT);
            subIdList = getUserIds(param);
            // 是否排除自己，以前的老逻辑为默认排除自己
            String userId = userEntity.getUserId();
            if (excludeOneSelf) {
                subIdList.remove(userId);
            } else {
                if (!subIdList.contains(userId)) {
                    subIdList.add(userId);
                }
            }
        }else{
            subIdList = getSubIdsByDataPermission(userEntity, viewPermission, excludeOneSelf);
        }

        return subIdList;
    }


    /**
     * Description:
     * @param dataPermission 数据权限
     * @param userId 需要获取下属员工userId列表的员工
     * @param corpid 需要获取下属员工userId列表的员工
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工、且包含隐藏员工
     * @param excludeOneSelf 是否排除自己，true 则排除自己，false不排除
     * @return java.util.List<java.lang.String>
     * @author 魏荣杰
     * @date 2020/6/4 9:41 下午
     */
    @Override
    public List<String> getSubIdListByDataPermission(Integer dataPermission, String userId, String corpid, int viewPermission, boolean excludeOneSelf) {
        List<String> userIds = new ArrayList<>();
        if (StringUtil.isEmpty(userId)) {
            throw new IllegalArgumentException("userId 不能为空");
        }
        if (StringUtil.isEmpty(corpid)) {
            throw new IllegalArgumentException("corpid 不能为空");
        }
        if (dataPermission == null) {
            throw new IllegalArgumentException("dataPermission 不能为null");
        }
        DataPermissionEnum dataPermissionEnum = DataPermissionEnum.getByCode(dataPermission);
        if(dataPermissionEnum == null){
            return userIds;
        }
        List<Long> depIdIn;
        Map<String,Object> param = new HashMap<>(16);
        switch (dataPermissionEnum) {
            case SELF:
                //本人
                userIds.add(userId);
                break;
            case DEPARTMENT:
                //本部门
                depIdIn = getUserBelongDeptIdList(corpid, userId, true);
                userIds = getDepUserIdList(corpid, depIdIn, viewPermission);
                break;
            case DEPARTMENT_RECURSION:
                //本部门和下属部门
                depIdIn = getUserBelongDeptIdList(corpid, userId, true);
                depIdIn = departmentModel.getSubDepIdList(corpid, depIdIn);
                userIds = getDepUserIdList(corpid, depIdIn, viewPermission);
                break;
            case CUSTOM:
                //自定义
                List<Long> weakManageDepIdList = new ArrayList<>();
                Set<String> userIdSet = new HashSet<>();
                param.put("supStaffId", userId);
                param.put("corpid", corpid);
                param.put("del", 0);
                List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
                depIdIn = new ArrayList<>();
                for(WeakManageEntity weakManage : weakManageList){
                    Integer type = weakManage.getType();
                    if(type.equals(1)){
                        userIdSet.add(weakManage.getSubStaffId());
                    }else if(type.equals(2)){
                        Long subDepId = weakManage.getSubDepId();
                        if (subDepId != null) {
                            depIdIn.add(subDepId);
                        }
                    }
                }
                if (depIdIn.size() > 0) {
                    param.clear();
                    param.put("corpid", corpid);
                    param.put("del", 0);
                    param.put("idIn", depIdIn);
                    weakManageDepIdList = departmentModel.getDepIds(param);
                }
                if(!weakManageDepIdList.isEmpty()){
                    List<String> tempUserIds = getDepUserIdList(corpid, weakManageDepIdList, viewPermission);
                    userIdSet.addAll(tempUserIds);
                }

                userIds = new ArrayList<>(userIdSet);
                break;
            case ALL:
                //全公司
                param.put("corpid", corpid);
                //viewPermission = 1，则包含离职员工、且包含隐藏员工
                if (viewPermission != 1) {
                    param.put("del", 0);
                }
                param.put("start", 0);
                param.put("pageNum", BasicConstant.MAX_USER_COUNT);
                userIds = getUserIds(param);
                break;
            default:
                break;
        }
        if (excludeOneSelf) {
            userIds.remove(userId);
        } else {
            userIds.add(userId);
        }
        return new ArrayList<>(new HashSet<>(userIds));
    }


    /**
     * Description:
     * @param dataPermission 数据权限
     * @param userId 需要获取下属员工userId列表的员工
     * @param corpid 需要获取下属员工userId列表的员工
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工、且包含隐藏员工
     * @param excludeOneSelf 是否排除自己，true 则排除自己，false不排除
     * @return java.util.List<java.lang.String>
     * @author 魏荣杰
     * @date 2020/6/4 9:41 下午
     */
    @Override
    public List<String> getSubIdListByDataPermission4Visible(Integer dataPermission, String userId, String corpid, int viewPermission, boolean excludeOneSelf) {
        List<String> userIds = new ArrayList<>();
        if (StringUtil.isEmpty(userId)) {
            throw new IllegalArgumentException("userId 不能为空");
        }
        if (StringUtil.isEmpty(corpid)) {
            throw new IllegalArgumentException("corpid 不能为空");
        }
        if (dataPermission == null) {
            throw new IllegalArgumentException("dataPermission 不能为null");
        }
        DataPermissionEnum dataPermissionEnum = DataPermissionEnum.getByCode(dataPermission);
        if(dataPermissionEnum == null){
            return userIds;
        }
        List<Long> depIdIn;
        Map<String,Object> param = new HashMap<>(16);
        switch (dataPermissionEnum) {
            case SELF:
                //本人
                userIds.add(userId);
                break;
            case DEPARTMENT:
                //本部门
                depIdIn = getUserBelongDeptIdList(corpid, userId, true);
                userIds = getDepUserIdList4Visible(corpid, depIdIn, viewPermission);
                break;
            case DEPARTMENT_RECURSION:
                //本部门和下属部门
                depIdIn = getUserBelongDeptIdList(corpid, userId, true);
                depIdIn = departmentModel.getSubDepIdList(corpid, depIdIn);
                userIds = getDepUserIdList4Visible(corpid, depIdIn, viewPermission);
                break;
            case CUSTOM:
                //自定义
                List<Long> weakManageDepIdList = new ArrayList<>();
                Set<String> userIdSet = new HashSet<>();
                param.put("supStaffId", userId);
                param.put("corpid", corpid);
                param.put("del", 0);
                List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
                depIdIn = new ArrayList<>();
                for(WeakManageEntity weakManage : weakManageList){
                    Integer type = weakManage.getType();
                    if(type.equals(1)){
                        userIdSet.add(weakManage.getSubStaffId());
                    }else if(type.equals(2)){
                        Long subDepId = weakManage.getSubDepId();
                        if (subDepId != null) {
                            depIdIn.add(subDepId);
                        }
                    }
                }
                if (depIdIn.size() > 0) {
                    param.clear();
                    param.put("corpid", corpid);
                    param.put("del", 0);
                    param.put("idIn", depIdIn);
                    weakManageDepIdList = departmentModel.getDepIds(param);
                }
                if(!weakManageDepIdList.isEmpty()){
                    List<String> tempUserIds = getDepUserIdList4Visible(corpid, weakManageDepIdList, viewPermission);
                    userIdSet.addAll(tempUserIds);
                }

                userIds = new ArrayList<>(userIdSet);
                break;
            case ALL:
                //全公司
                param.put("corpid", corpid);
                //viewPermission = 1，则包含离职员工，不包含不在可见范围内员工
                if (viewPermission != 1) {
                    param.put("del", 0);
                } else {
                    param.put("negDel", 2);
                }
                param.put("start", 0);
                param.put("pageNum", BasicConstant.MAX_USER_COUNT);
                userIds = getUserIds(param);
                break;
            default:
                break;
        }
        if (excludeOneSelf) {
            userIds.remove(userId);
        } else {
            userIds.add(userId);
        }
        return new ArrayList<>(new HashSet<>(userIds));
    }


    @Override
    public Integer getDataPermission(UserVO userVO, boolean isOrganization) throws IllegalArgumentException {
        return getDataPermission(userVO.getDataPermissionDetail(), userVO.getCorpid(), userVO.getRoleIds(), isOrganization);
    }
    @Override
    public Integer getDataPermission(UserEntity userEntity, boolean isOrganization) throws IllegalArgumentException {
        if (userEntity == null) {
            throw new IllegalArgumentException("userEntity 不能为 NULL");
        }

        return getDataPermission(userEntity.getDataPermissionDetail(), userEntity.getCorpid(), userEntity.getRoleIds(), isOrganization);
    }
    /**
     * Description: 获取数据权限
     * 使用前需要使用 com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil#setValue
     * @param dataPermissionDetail 用户
     *
     * @param isOrganization 是否是组织架构 true 是， false不是
     * @return java.lang.Integer
     * @author 魏荣杰
     * @date 2020/4/30 2:32 下午
     */
    @Override
    public Integer getDataPermission(Map<String, Integer> dataPermissionDetail, String corpid, String rolesStr, boolean isOrganization) throws IllegalArgumentException {

        if (isOrganization) {
           if (dataPermissionDetail != null) {
               Integer dataPermission = dataPermissionDetail.get(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.SYSTEM.getCode());
               if (!Objects.isNull(dataPermission)) {
                   return dataPermission;
               }
           }
        } else {
            // 如果前置逻辑已经计算出改用户的最大数据权限(比如使用网关计算好的userVO的最大数据权限)，则不再重新计算
            DataPermissionParamsPojo dataPermissionParamsPojoValue = TransmittableThreadLocalUtil.getDataPermissionParamsPojoValue();
            SaasMarkEnum saasMarkEnum = SaasMarkEnum.getMemo(dataPermissionParamsPojoValue.getSaasMark());
            Integer businessType = dataPermissionParamsPojoValue.getBusinessType();
            Long menuId = dataPermissionParamsPojoValue.getMenuId();
            if (dataPermissionDetail != null) {
                String key = null;
                if (!Objects.isNull(saasMarkEnum)) {
                    switch (saasMarkEnum) {
                        case SAAS:
                            key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + businessType;
                            break;
                        case PAAS:
                            key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + menuId;
                            break;
                        case THIRD_PARTY:
                        default:
                    }
                    if (!Objects.isNull(key)) {
                        Integer dataPermission = dataPermissionDetail.get(key);
                        if (!Objects.isNull(dataPermission)) {
                            return dataPermission;
                        }
                    }
                }
            }
        }

        // 最小 dataPermission 为1
        Integer dataPermission = DataPermissionEnum.SELF.getCode();

        if(StringUtil.isEmpty(rolesStr)){
            //没有角色则默认是最小 dataPermission = 1
            return dataPermission;
        }
        String[] roleArray = rolesStr.split("\\|");
        List<Integer> roleIdIn = new ArrayList<>();
        for(String roleStr : roleArray){
            if(!StringUtil.isEmpty(roleStr)){
                roleIdIn.add(StringUtil.toInt(roleStr, 0));
            }
        }
        if(roleIdIn.size() == 0){
            //没有角色则默认是最小 dataPermission = 1
            return dataPermission;
        }

        List<RoleEntity> roleList = roleModel.getByRoleIdIn(corpid, roleIdIn, true);


        //数据权限封装
        Map<String, Integer> dataPermissionsDetail = new HashMap<>();
        Map<String, Object> params= new HashMap<>();
        params.put("aliasIn", ProPermissionAliasEnum.getFormPermissionAlias());
        List<ProPermissionEntity> proPermissionEntityList = proPermissionModel.findEntitys(params);
        // 管理中心中的组织权限id
        Integer organizationSetId = null;
        Map<Integer, Integer> permissionIdAndBusinessTypeMap = new HashMap<>();
        for (ProPermissionEntity entity : proPermissionEntityList) {
            String alias = entity.getAlias();
            ProPermissionAliasEnum proPermissionAliasEnum = ProPermissionAliasEnum.getByAlias(alias);
            if (!Objects.isNull(proPermissionAliasEnum)) {
                switch (proPermissionAliasEnum) {
                    case CUSTOMER_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        break;
                    case CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTACT.getCode());
                        break;
                    case CUSTOMER_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
                        break;
                    case COMMUNICATE_PLAN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.COMMUNICATE_PLAN.getCode());
                        break;
                    case SALES_OPPORTUNITY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
                        break;
                    case CONTRACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT.getCode());
                        break;
                    case SIGN_IN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SIGNIN.getCode());
                        break;
                    case WORK_REPORT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_REPORT.getCode());
                        break;
                    case QUOTATION:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.QUOTATION.getCode());
                        break;
                    case REFUND:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.REFUND.getCode());
                        break;
                    case SUPPLIER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER.getCode());
                        break;
                    case SUPPLIER_CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER_CONTACT.getCode());
                        break;
                    case SUPPLIER_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER_COMMUNICATE.getCode());
                        break;
                    case PURCHASE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE.getCode());
                        break;
                    case RETURNED_PURCHASE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
                        break;
                    case ASSEMBLE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ASSEMBLE.getCode());
                        break;
                    case INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_INSTOCK.getCode());
                        break;
                    case PURCHASE_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE_INSTOCK.getCode());
                        break;
                    case REFUND_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.REFUND_INSTOCK.getCode());
                        break;
                    case PRODUCTION_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode());
                        break;
                    case RETURNED_MATERIEL_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
                        break;
                    case OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_OUTSTOCK.getCode());
                        break;
                    case CONTRACT_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode());
                        break;
                    case RETURNED_PURCHASE_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode());
                        break;
                    case PRODUCTION_MATERIEL_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode());
                        break;
                    case WORK_ORDER_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode());
                        break;
                    case INVENTORY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.INVENTORY.getCode());
                        break;
                    case TRANSFER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.TRANSFER.getCode());
                        break;
                    case WAREHOUSE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WAREHOUSE.getCode());
                        break;
                    case STOCK_SEARCH:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.STOCK_SEARCH.getCode());
                        break;
                    case BOM_BILL:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.BOM_BILL.getCode());
                        break;
                    case PRODUCTION_ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
                        break;
                    case PRODUCT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCT.getCode());
                        break;
                    case PAYMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT.getCode());
                        break;
                    case PAYMENT_SHEET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        break;
                    case PAY_PLAN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAY_PLAN.getCode());
                        break;
                    case INVOICE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.INVOICE.getCode());
                        break;
                    case WORK_ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER.getCode());
                        break;
                    case ORGANIZATION_SET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SYSTEM.getCode());
                        organizationSetId = entity.getId();
                        break;
                    case PURCHASE_INVOICE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
                        break;
                    case PAY_SHEET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAY_SHEET.getCode());
                        break;
                    case DISTRIBUTOR_PROFILE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode());
                        break;
                    case DISTRIBUTOR_CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_CONTACT.getCode());
                        break;
                    case DISTRIBUTOR_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_COMMUNICATE.getCode());
                        break;
                    case ACCOUNT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_ACCOUNT.getCode());
                        break;
                    case ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ORDER.getCode());
                        break;
                    case STATEMENTLIST:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_STATEMENT_STATISTIC.getCode());
                        break;
                    case RETURN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURN.getCode());
                        break;
                    case MARKET_ACTIVITY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKET_ACTIVITY.getCode());
                        break;
                    case CLUE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CLUE.getCode());
                        break;
                    case OTHER_INCOME:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_INCOME.getCode());
                        break;
                    case OTHER_EXPENSE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_EXPENSE.getCode());
                        break;
                    case FUND_TRANSFER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.FUND_TRANSFER.getCode());
                        break;
                    case MARKET_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKET_MANAGEMENT.getCode());
                        break;
                    case MARKETING_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKETING_MANAGEMENT.getCode());
                        break;
                    case ORDER_CENTER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ORDER_CENTER.getCode());
                        break;
                    case DISTRIBUTOR_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode());
                        break;
                    default:
                }
            }
        }

        for (RoleEntity role : roleList) {

            if (role.getDataPermission() > dataPermission && dataPermission < 5) {
                dataPermission = role.getDataPermission();
            }

            // 每个role的数据权限处理
            String dataPermissionDetailStr = role.getDataPermissionDetail();
            List<DataPermissionDetailPojo> dataPermissionDetailPojos = JSON.parseArray(dataPermissionDetailStr, DataPermissionDetailPojo.class);
            if (dataPermissionDetailPojos == null) {
                dataPermissionDetailPojos = new ArrayList<>();
            }
            // SaaS表单的数据权限map
            Map<Long, Integer> saasIdAndDataPermissionMap = new HashMap<>();
            // PaaS表单的数据权限map
            Map<Long, Integer> paasIdAndDataPermissionMap = new HashMap<>();
            for (DataPermissionDetailPojo pojo : dataPermissionDetailPojos) {
                List<DataPermissionsPojo> permissions = pojo.getPermissions();
                for (DataPermissionsPojo dataPermissionsPojo : permissions) {
                    if (Objects.equals(SaasMarkEnum.SAAS.getCode(), dataPermissionsPojo.getSaasMark())) {
                        saasIdAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    } else {
                        paasIdAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    }
                }
            }

            // SaaS数据权限处理，封到表单级
            Set<Integer> permissionIds = role.getPermissionIdsSet();
            permissionIds.add(organizationSetId);
            for (Integer permissionId : permissionIds) {
                if (permissionIdAndBusinessTypeMap.containsKey(permissionId)) {
                    String key = SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + permissionIdAndBusinessTypeMap.get(permissionId).toString();
                    if (dataPermissionsDetail.containsKey(key)) {
                        Integer permission = dataPermissionsDetail.get(key);
                        if (saasIdAndDataPermissionMap.containsKey(permissionId.longValue())) {
                            if (permission < saasIdAndDataPermissionMap.getOrDefault(permissionId.longValue(), 1)) {
                                dataPermissionsDetail.put(key, saasIdAndDataPermissionMap.get(permissionId.longValue()));
                            }
                        } else {
                            if (permission < role.getDataPermission()) {
                                dataPermissionsDetail.put(key, role.getDataPermission());
                            }
                        }
                    } else {
                        if (saasIdAndDataPermissionMap.containsKey(permissionId.longValue())) {
                            dataPermissionsDetail.put(key, saasIdAndDataPermissionMap.get(permissionId.longValue()));
                        } else {
                            dataPermissionsDetail.put(key, role.getDataPermission());
                        }
                    }
                }
            }

            // 追加 预收款：客户数据权限   预付款：供应商数据权限
            List<XbbRefTypeEnum> specialDataPermissionXbbRefTypes = Arrays.asList(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, XbbRefTypeEnum.SUPPLIER);
            for (XbbRefTypeEnum type : specialDataPermissionXbbRefTypes) {
                Integer permission = dataPermissionsDetail.getOrDefault(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + type.getCode(), DataPermissionEnum.SELF.getCode());
                if (Objects.equals(type, XbbRefTypeEnum.CUSTOMER_MANAGEMENT)) {
                    dataPermissionsDetail.put(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(), permission);
                }
                if (Objects.equals(type, XbbRefTypeEnum.SUPPLIER)) {
                    dataPermissionsDetail.put(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.PREPAY_BALANCE.getCode(), permission);
                }
            }

            // saas内paas表单的权限处理
            params.clear();
            params.put("columns", "id");
            params.put("corpid", corpid);
            params.put("aliasIn", Arrays.asList(SystemAppMenuEnum.CRM.getAlias(), SystemAppMenuEnum.JXC.getAlias(), SystemAppMenuEnum.PRODUCT.getAlias(), SystemAppMenuEnum.FUND_MANAGEMENT.getAlias()));
            params.put("del", 0);
            List<PaasAppEntity> paasAppEntities = paasAppDao.findEntitys(params);
            List<Long> appIds = new ArrayList<>();
            for (PaasAppEntity paasAppEntity : paasAppEntities) {
                appIds.add(paasAppEntity.getId());
            }

            params.clear();
            params.put("corpid", corpid);
            params.put("appIdIn", appIds);
            params.put("saasMark", SaasMarkEnum.PAAS.getCode());
            params.put("columns", "menu_id");
            params.put("del", 0);
            List<PaasFormEntity> paasFormEntities = paasFormDao.findEntity(params);
            for (PaasFormEntity paasFormEntity : paasFormEntities) {
                Long menuId = paasFormEntity.getMenuId();
                String key = SaasMarkEnum.PAAS.getCode() + StringConstant.UNDER_LINE + menuId;
                if (dataPermissionsDetail.containsKey(key)) {
                    Integer permission = dataPermissionsDetail.get(key);
                    if (paasIdAndDataPermissionMap.containsKey(menuId)) {
                        if (permission < paasIdAndDataPermissionMap.getOrDefault(menuId, 1)) {
                            dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(menuId));
                        }
                    } else {
                        if (permission < role.getDataPermission()) {
                            dataPermissionsDetail.put(key, role.getDataPermission());
                        }
                    }
                } else {
                    if (paasIdAndDataPermissionMap.containsKey(menuId)) {
                        dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(menuId));
                    } else {
                        dataPermissionsDetail.put(key, role.getDataPermission());
                    }
                }
            }


            // 数据权限PaaS部分
            List<AppPermissionPojo> appPerms = JSON.parseArray(role.getPaasPermissions(), AppPermissionPojo.class);
            if (Objects.nonNull(appPerms)) {
                for (AppPermissionPojo appPermissionPojo : appPerms) {
                    List<ModulePermissionPojo> modules = appPermissionPojo.getModules();
                    for (ModulePermissionPojo module : modules) {
                        String key = SaasMarkEnum.PAAS.getCode() + StringConstant.UNDER_LINE + module.getId();
                        if (dataPermissionsDetail.containsKey(key)) {
                            Integer permission = dataPermissionsDetail.get(key);
                            if (paasIdAndDataPermissionMap.containsKey(module.getId())) {
                                if (permission < paasIdAndDataPermissionMap.getOrDefault(module.getId(), 1)) {
                                    dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(module.getId()));
                                }
                            } else {
                                if (permission < role.getDataPermission()) {
                                    dataPermissionsDetail.put(key, role.getDataPermission());
                                }
                            }
                        } else {
                            if (paasIdAndDataPermissionMap.containsKey(module.getId())) {
                                dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(module.getId()));
                            } else {
                                dataPermissionsDetail.put(key, role.getDataPermission());
                            }
                        }
                    }
                }
            }

        }

        String key = null;
        if (isOrganization) {
            Integer organizationDataPermission = dataPermissionsDetail.get(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.SYSTEM.getCode());
            if (!Objects.isNull(organizationDataPermission)) {
                return organizationDataPermission;
            }
        } else {
            // 如果前置逻辑已经计算出改用户的最大数据权限(比如使用网关计算好的userVO的最大数据权限)，则不再重新计算
            DataPermissionParamsPojo dataPermissionParamsPojoValue = TransmittableThreadLocalUtil.getDataPermissionParamsPojoValue();
            SaasMarkEnum saasMarkEnum = SaasMarkEnum.getMemo(dataPermissionParamsPojoValue.getSaasMark());
            Integer businessType = dataPermissionParamsPojoValue.getBusinessType();
            Long menuId = dataPermissionParamsPojoValue.getMenuId();
            if (!Objects.isNull(saasMarkEnum)) {
                switch (saasMarkEnum) {
                    case SAAS:
                        key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + businessType;
                        break;
                    case PAAS:
                        key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + menuId;
                        break;
                    case THIRD_PARTY:
                    default:
                }
                if (!Objects.isNull(key)) {
                    Integer permission = dataPermissionsDetail.get(key);
                    if (!Objects.isNull(permission)) {
                        return permission;
                    }
                }
            }
        }



        return dataPermission;
    }

    /**
     * 获取员工 dataPermission
     * @param userEntity 需要获取dataPermission的员工
     * @return 5：全公司 4：自定义 3：本部门和下属部门，2本部门 1：本人。具体值请对应DataPermissionEnum枚举
     */
    @Override
    public Integer getDataPermission(UserEntity userEntity) throws IllegalArgumentException {
        return getDataPermission(userEntity, false);
    }

    @Override
    public Integer getDataPermission(UserEntity userEntity, SaasMarkEnum saasMarkEnum, Integer businessType, Long menuId) {
        if(userEntity == null){
            throw new IllegalArgumentException("userEntity 不能为 NULL");
        }
        if (saasMarkEnum == null) {
            throw new IllegalArgumentException("saasMarkEnum 不能为 NULL");
        }
        if (businessType == null && menuId == null) {
            throw new IllegalArgumentException("businessType，menuId 不能均为 NULL");
        }

        if (userEntity.getDataPermissionDetail() != null) {
            String key = null;
            switch (saasMarkEnum) {
                case SAAS:
                    key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + businessType;
                    break;
                case PAAS:
                    key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + menuId;
                    break;
                case THIRD_PARTY:
                default:
            }
            if (!Objects.isNull(key)) {
                Integer dataPermission = userEntity.getDataPermissionDetail().get(key);
                if (!Objects.isNull(dataPermission)) {
                    return dataPermission;
                }
            }
        }

        // 最小 dataPermission 为1
        Integer dataPermission = DataPermissionEnum.SELF.getCode();

        String rolesStr = userEntity.getRoleIds();
        if(StringUtil.isEmpty(rolesStr)){
            //没有角色则默认是最小 dataPermission = 1
            return dataPermission;
        }
        String[] roleArray = rolesStr.split("\\|");
        List<Integer> roleIdIn = new ArrayList<>();
        for(String roleStr : roleArray){
            if(!StringUtil.isEmpty(roleStr)){
                roleIdIn.add(StringUtil.toInt(roleStr, 0));
            }
        }
        if(roleIdIn.size() == 0){
            //没有角色则默认是最小 dataPermission = 1
            return dataPermission;
        }

        List<RoleEntity> roleList = roleModel.getByRoleIdIn(userEntity.getCorpid(), roleIdIn, true);


        //数据权限封装
        Map<String, Integer> dataPermissionsDetail = new HashMap<>();
        Map<String, Object> params= new HashMap<>();
        params.put("aliasIn", ProPermissionAliasEnum.getFormPermissionAlias());
        List<ProPermissionEntity> proPermissionEntityList = proPermissionModel.findEntitys(params);
        // 管理中心中的组织权限id
        Integer organizationSetId = null;
        Map<Integer, Integer> permissionIdAndBusinessTypeMap = new HashMap<>();
        for (ProPermissionEntity entity : proPermissionEntityList) {
            String alias = entity.getAlias();
            ProPermissionAliasEnum proPermissionAliasEnum = ProPermissionAliasEnum.getByAlias(alias);
            if (!Objects.isNull(proPermissionAliasEnum)) {
                switch (proPermissionAliasEnum) {
                    case CUSTOMER_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        break;
                    case CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTACT.getCode());
                        break;
                    case CUSTOMER_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
                        break;
                    case COMMUNICATE_PLAN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.COMMUNICATE_PLAN.getCode());
                        break;
                    case SALES_OPPORTUNITY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
                        break;
                    case CONTRACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT.getCode());
                        break;
                    case SIGN_IN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SIGNIN.getCode());
                        break;
                    case WORK_REPORT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_REPORT.getCode());
                        break;
                    case QUOTATION:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.QUOTATION.getCode());
                        break;
                    case REFUND:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.REFUND.getCode());
                        break;
                    case SUPPLIER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER.getCode());
                        break;
                    case SUPPLIER_CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER_CONTACT.getCode());
                        break;
                    case SUPPLIER_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER_COMMUNICATE.getCode());
                        break;
                    case PURCHASE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE.getCode());
                        break;
                    case RETURNED_PURCHASE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
                        break;
                    case ASSEMBLE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ASSEMBLE.getCode());
                        break;
                    case INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_INSTOCK.getCode());
                        break;
                    case PURCHASE_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE_INSTOCK.getCode());
                        break;
                    case REFUND_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.REFUND_INSTOCK.getCode());
                        break;
                    case PRODUCTION_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode());
                        break;
                    case RETURNED_MATERIEL_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
                        break;
                    case OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_OUTSTOCK.getCode());
                        break;
                    case CONTRACT_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode());
                        break;
                    case RETURNED_PURCHASE_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode());
                        break;
                    case PRODUCTION_MATERIEL_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode());
                        break;
                    case WORK_ORDER_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode());
                        break;
                    case INVENTORY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.INVENTORY.getCode());
                        break;
                    case TRANSFER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.TRANSFER.getCode());
                        break;
                    case WAREHOUSE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WAREHOUSE.getCode());
                        break;
                    case STOCK_SEARCH:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.STOCK_SEARCH.getCode());
                        break;
                    case BOM_BILL:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.BOM_BILL.getCode());
                        break;
                    case PRODUCTION_ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
                        break;
                    case PRODUCT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCT.getCode());
                        break;
                    case PAYMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT.getCode());
                        break;
                    case PAYMENT_SHEET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        break;
                    case PAY_PLAN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAY_PLAN.getCode());
                        break;
                    case INVOICE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.INVOICE.getCode());
                        break;
                    case WORK_ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER.getCode());
                        break;
                    case ORGANIZATION_SET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SYSTEM.getCode());
                        organizationSetId = entity.getId();
                        break;
                    case PURCHASE_INVOICE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
                        break;
                    case PAY_SHEET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAY_SHEET.getCode());
                        break;
                    case MARKET_ACTIVITY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKET_ACTIVITY.getCode());
                        break;
                    case CLUE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CLUE.getCode());
                        break;
                    case PAYMENT_TASK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT_TASK.getCode());
                        break;
                    case DISTRIBUTOR_PROFILE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode());
                        break;
                    case DISTRIBUTOR_CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_CONTACT.getCode());
                        break;
                    case DISTRIBUTOR_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_COMMUNICATE.getCode());
                        break;
                    case ACCOUNT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_ACCOUNT.getCode());
                        break;
                    case ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ORDER.getCode());
                        break;
                    case STATEMENTLIST:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_STATEMENT_STATISTIC.getCode());
                        break;
                    case RETURN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURN.getCode());
                        break;
                    case OTHER_INCOME:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_INCOME.getCode());
                        break;
                    case OTHER_EXPENSE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_EXPENSE.getCode());
                        break;
                    case FUND_TRANSFER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.FUND_TRANSFER.getCode());
                        break;
                    case MARKET_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKET_MANAGEMENT.getCode());
                        break;
                    case MARKETING_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKETING_MANAGEMENT.getCode());
                        break;
                    case ORDER_CENTER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ORDER_CENTER.getCode());
                        break;
                    case DISTRIBUTOR_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode());
                        break;
                    default:
                }
            }
        }

        for (RoleEntity role : roleList) {

            if (role.getDataPermission() > dataPermission && dataPermission < 5) {
                dataPermission = role.getDataPermission();
            }

            // 每个role的数据权限处理
            String dataPermissionDetailStr = role.getDataPermissionDetail();
            List<DataPermissionDetailPojo> dataPermissionDetailPojos = JSON.parseArray(dataPermissionDetailStr, DataPermissionDetailPojo.class);
            if (dataPermissionDetailPojos == null) {
                dataPermissionDetailPojos = new ArrayList<>();
            }
            // SaaS表单的数据权限map
            Map<Long, Integer> saasIdAndDataPermissionMap = new HashMap<>();
            // PaaS表单的数据权限map
            Map<Long, Integer> paasIdAndDataPermissionMap = new HashMap<>();
            for (DataPermissionDetailPojo pojo : dataPermissionDetailPojos) {
                List<DataPermissionsPojo> permissions = pojo.getPermissions();
                for (DataPermissionsPojo dataPermissionsPojo : permissions) {
                    if (Objects.equals(SaasMarkEnum.SAAS.getCode(), dataPermissionsPojo.getSaasMark())) {
                        saasIdAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    } else {
                        paasIdAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    }
                }
            }

            // SaaS数据权限处理，封到表单级
            Set<Integer> permissionIds = role.getPermissionIdsSet();
            permissionIds.add(organizationSetId);
            for (Integer permissionId : permissionIds) {
                if (permissionIdAndBusinessTypeMap.containsKey(permissionId)) {
                    String key = SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + permissionIdAndBusinessTypeMap.get(permissionId).toString();
                    if (dataPermissionsDetail.containsKey(key)) {
                        Integer permission = dataPermissionsDetail.get(key);
                        if (saasIdAndDataPermissionMap.containsKey(permissionId.longValue())) {
                            if (permission < saasIdAndDataPermissionMap.getOrDefault(permissionId.longValue(), 1)) {
                                dataPermissionsDetail.put(key, saasIdAndDataPermissionMap.get(permissionId.longValue()));
                            }
                        } else {
                            if (permission < role.getDataPermission()) {
                                 dataPermissionsDetail.put(key, role.getDataPermission());
                            }
                        }
                    } else {
                        if (saasIdAndDataPermissionMap.containsKey(permissionId.longValue())) {
                            dataPermissionsDetail.put(key, saasIdAndDataPermissionMap.get(permissionId.longValue()));
                        } else {
                            dataPermissionsDetail.put(key, role.getDataPermission());
                        }
                    }
                }
            }

            // 追加 预收款：客户数据权限   预付款：供应商数据权限
            List<XbbRefTypeEnum> specialDataPermissionXbbRefTypes = Arrays.asList(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, XbbRefTypeEnum.SUPPLIER);
            for (XbbRefTypeEnum type : specialDataPermissionXbbRefTypes) {
                Integer permission = dataPermissionsDetail.getOrDefault(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + type.getCode(), DataPermissionEnum.SELF.getCode());
                if (Objects.equals(type, XbbRefTypeEnum.CUSTOMER_MANAGEMENT)) {
                    dataPermissionsDetail.put(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(), permission);
                }
                if (Objects.equals(type, XbbRefTypeEnum.SUPPLIER)) {
                    dataPermissionsDetail.put(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.PREPAY_BALANCE.getCode(), permission);
                }
            }

            // saas内paas表单的权限处理
            params.clear();
            params.put("columns", "id");
            params.put("corpid", userEntity.getCorpid());
            params.put("aliasIn", Arrays.asList(SystemAppMenuEnum.CRM.getAlias(), SystemAppMenuEnum.JXC.getAlias(), SystemAppMenuEnum.PRODUCT.getAlias(), SystemAppMenuEnum.FUND_MANAGEMENT.getAlias()));
            params.put("del", 0);
            List<PaasAppEntity> paasAppEntities = paasAppDao.findEntitys(params);
            List<Long> appIds = new ArrayList<>();
            for (PaasAppEntity paasAppEntity : paasAppEntities) {
                appIds.add(paasAppEntity.getId());
            }

            params.clear();
            params.put("corpid", userEntity.getCorpid());
            params.put("appIdIn", appIds);
            params.put("saasMark", SaasMarkEnum.PAAS.getCode());
            params.put("columns", "menu_id");
            params.put("del", 0);
            List<PaasFormEntity> paasFormEntities = paasFormDao.findEntity(params);
            for (PaasFormEntity paasFormEntity : paasFormEntities) {
                Long paasMenuId = paasFormEntity.getMenuId();
                String key = SaasMarkEnum.PAAS.getCode() + StringConstant.UNDER_LINE + paasMenuId;
                if (dataPermissionsDetail.containsKey(key)) {
                    Integer permission = dataPermissionsDetail.get(key);
                    if (paasIdAndDataPermissionMap.containsKey(paasMenuId)) {
                        if (permission < paasIdAndDataPermissionMap.getOrDefault(paasMenuId, 1)) {
                            dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(paasMenuId));
                        }
                    } else {
                        if (permission < role.getDataPermission()) {
                            dataPermissionsDetail.put(key, role.getDataPermission());
                        }
                    }
                } else {
                    if (paasIdAndDataPermissionMap.containsKey(paasMenuId)) {
                        dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(paasMenuId));
                    } else {
                        dataPermissionsDetail.put(key, role.getDataPermission());
                    }
                }
            }

            // 数据权限PaaS部分
            List<AppPermissionPojo> appPerms = JSON.parseArray(role.getPaasPermissions(), AppPermissionPojo.class);
            if (Objects.nonNull(appPerms)) {
                for (AppPermissionPojo appPermissionPojo : appPerms) {
                    List<ModulePermissionPojo> modules = appPermissionPojo.getModules();
                    for (ModulePermissionPojo module : modules) {
                        String key = SaasMarkEnum.PAAS.getCode() + StringConstant.UNDER_LINE + module.getId();
                        if (dataPermissionsDetail.containsKey(key)) {
                            Integer permission = dataPermissionsDetail.get(key);
                            if (paasIdAndDataPermissionMap.containsKey(module.getId())) {
                                if (permission < paasIdAndDataPermissionMap.getOrDefault(module.getId(), 1)) {
                                    dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(module.getId()));
                                }
                            } else {
                                if (permission < role.getDataPermission()) {
                                    dataPermissionsDetail.put(key, role.getDataPermission());
                                }
                            }
                        } else {
                            if (paasIdAndDataPermissionMap.containsKey(module.getId())) {
                                dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(module.getId()));
                            } else {
                                dataPermissionsDetail.put(key, role.getDataPermission());
                            }
                        }
                    }
                }
            }

        }

        String key = null;
        // 如果前置逻辑已经计算出改用户的最大数据权限(比如使用网关计算好的userVO的最大数据权限)，则不再重新计算
        switch (saasMarkEnum) {
            case SAAS:
                key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + businessType;
                break;
            case PAAS:
                key = saasMarkEnum.getCode() + StringConstant.UNDER_LINE + menuId;
                break;
            case THIRD_PARTY:
            default:
        }
        if (!Objects.isNull(key)) {
            Integer permission = dataPermissionsDetail.get(key);
            if (!Objects.isNull(permission)) {
                return permission;
            }
        }

        return dataPermission;

    }

    /**
     * 查询部门内的员工userId列表 -不包含离职员工 (抄 方法getDepUserIdList)
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @return 部门内的员工userId列表
     */
    @Override
    public List<UserDepartmentEntity> getUserDepEntitiesByDepIds(String corpid, Collection<Long> depIdIn) {
        List<UserDepartmentEntity> res = new ArrayList<>();
        if (depIdIn.size() <= 0) {
            return res;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("departmentIdIn", depIdIn);
        param.put("del", 0);
        List entitys = userDepartmentModel.findEntitys(param);
        res.addAll(entitys);
        return res;
    }

    /**
     * 查询部门内的员工userId列表
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @return 部门内的员工userId列表
     */
    @Override
    public List<String> getDepUserIdList(String corpid, Collection<Long> depIdIn, int viewPermission){

        List<String> depUserIdList = new ArrayList<>();
        if (depIdIn.size() <= 0) {
            return depUserIdList;
        }

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("depIdIn", depIdIn);
        if (viewPermission != 1) {
            param.put("del", 0);
            //mapper内改方法已改为不连表--该方法访问的是表tb_user_department
            depUserIdList = getUserIdsJoin(param);
        }else {
            /*
             * 对于离职员工和换部门的员工，表tb_user_department内的del字段都为1，因此要对换部门的员工（员工状态正常、未离职）进行排除
             */
            //该部门的正常员工（未删除、未离职、未换部门）
            param.put("del", 0);
            //mapper内改方法已改为不连表
            depUserIdList = getUserIdsJoin(param);

            //离职员工、换部门员工处理：排除换部门的员工
            param.remove("del");
            param.put("negDel", 0);
            List<String> leaveUserIdList = getUserIdsJoin(param);
            if (leaveUserIdList != null && leaveUserIdList.size() > 0) {
                param.clear();
                param.put("corpid", corpid);
                //leaveUserIdList内存放的是在该部门del=1的员工ids，要把换部门的排除（即排除未离职的）
                param.put("userIdIn", leaveUserIdList);
                //离职员工、隐藏员工（离职的or隐藏的本质上还属于该部门）
                param.put("negDel", 0);
                List<String> userIdList = getUserIds(param);

                depUserIdList.addAll(userIdList);
            }
        }

        return depUserIdList;
    }/**
     * 通过数据权限，获取管理的员工userId列表, 可以选择排除或不排除自己
     * 5：全公司 4：自定义 3：本部门和下属部门，2本部门 1：本人
     * @param userEntity userEntity
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @param excludeOneSelf 是否排除自己，true 则排除自己，false不排除
     * @return 管理的员工userId列表
     * @author kaka
     */
    @Override
    public List<String> getSubIdsByDataPermission(UserEntity userEntity, int viewPermission, boolean excludeOneSelf){
        Integer dataPermission = getDataPermission(userEntity);
        DataPermissionEnum dataPermissionEnum = DataPermissionEnum.getByCode(dataPermission);
        List<String> userIds = new ArrayList<>();
        if(dataPermissionEnum == null){
            return userIds;
        }
        String corpid = userEntity.getCorpid();
        List<Long> depIdIn;
        Map<String,Object> param = new HashMap<>(16);
        switch (dataPermissionEnum) {
            case SELF:
                //本人
                userIds.add(userEntity.getUserId());
                break;
            case DEPARTMENT:
                //本部门
                depIdIn = getUserBelongDeptIdList(userEntity, true);
                userIds = getDepUserIdList(corpid, depIdIn, viewPermission);
                break;
            case DEPARTMENT_RECURSION:
                //本部门和下属部门
                depIdIn = getManagementDepIdList(userEntity);
                userIds = getDepUserIdList(corpid, depIdIn, viewPermission);
                break;
            case CUSTOM:
                //自定义
                List<Long> weakManageDepIdList = new ArrayList<>();
                Set<String> userIdSet = new HashSet<>();
                String supUserId = userEntity.getUserId();
                param.put("supStaffId", supUserId);
                param.put("corpid", corpid);
                param.put("del", 0);
                List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
                depIdIn = new ArrayList<>();
                for(WeakManageEntity weakManage : weakManageList){
                    Integer type = weakManage.getType();
                    if(type.equals(1)){
                        userIdSet.add(weakManage.getSubStaffId());
                    }else if(type.equals(2)){
                        Long subDepId = weakManage.getSubDepId();
                        if (subDepId != null) {
                            depIdIn.add(subDepId);
                        }
                    }
                }
                if (depIdIn.size() > 0) {
                    param.clear();
                    param.put("corpid", corpid);
                    param.put("del", 0);
                    param.put("idIn", depIdIn);
                    weakManageDepIdList = departmentModel.getDepIds(param);
                }
                if(!weakManageDepIdList.isEmpty()){
                    List<String> tempUserIds = getDepUserIdList(corpid, weakManageDepIdList, viewPermission);
                    userIdSet.addAll(tempUserIds);
                }

                userIds = new ArrayList<>(userIdSet);
                break;
            case ALL:
                //全公司
                param.put("corpid", corpid);
                //viewPermission = 1，则包含离职员工、且包含隐藏员工
                if (viewPermission != 1) {
                    param.put("del", 0);
                }
                param.put("start", 0);
                param.put("pageNum", BasicConstant.MAX_USER_COUNT);
                userIds = getUserIds(param);
                break;
            default:
                break;
        }
        String userId = userEntity.getUserId();
        if (excludeOneSelf) {
            userIds.remove(userId);
        } else {
            userIds.add(userId);
        }
        return new ArrayList<>(new HashSet<>(userIds));
    }

    /**
     * 查询部门内的员工userId列表
     * @param corpid 公司corpid
     * @param depIdIn 要查询的部门id集合
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @return 部门内的员工userId列表
     */
    @Override
    public List<String> getDepUserIdList4Visible(String corpid, Collection<Long> depIdIn, int viewPermission){

        List<String> depUserIdList = new ArrayList<>();
        if (depIdIn.size() <= 0) {
            return depUserIdList;
        }

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("depIdIn", depIdIn);
        if (viewPermission != 1) {
            param.put("del", 0);
            //mapper内改方法已改为不连表--该方法访问的是表tb_user_department
            depUserIdList = getUserIdsJoin(param);
        }else {
            /*
             * 对于离职员工和换部门的员工，表tb_user_department内的del字段都为1，因此要对换部门的员工（员工状态正常、未离职）进行排除
             */
            //该部门的正常员工（未删除、未离职、未换部门）
            param.put("del", 0);
            //mapper内改方法已改为不连表
            depUserIdList = getUserIdsJoin(param);

            //离职员工、换部门员工处理：排除换部门的员工
            param.put("del", 1);
            List<String> leaveUserIdList = getUserIdsJoin(param);
            if (leaveUserIdList != null && leaveUserIdList.size() > 0) {
                param.clear();
                param.put("corpid", corpid);
                //leaveUserIdList内存放的是在该部门del=1的员工ids，要把换部门的排除（即排除未离职的）
                param.put("userIdIn", leaveUserIdList);
                //离职员工（离职的or隐藏的本质上还属于该部门）
                param.put("del", 1);
                List<String> userIdList = getUserIds(param);

                depUserIdList.addAll(userIdList);
            }
        }

        return depUserIdList;
    }


//    @Override
//    @Deprecated
//    public List<String> getSubIdsByDataPermission(UserEntity userEntity, int viewPermission, boolean excludeOneSelf){
//        Integer dataPermission = getDataPermission(userEntity, true);
//        DataPermissionEnum dataPermissionEnum = DataPermissionEnum.getByCode(dataPermission);
//        List<String> userIds = new ArrayList<>();
//        if(dataPermissionEnum == null){
//            return userIds;
//        }
//        String corpid = userEntity.getCorpid();
//        List<Long> depIdIn;
//        Map<String,Object> param = new HashMap<>(16);
//        switch (dataPermissionEnum) {
//            case SELF:
//                //本人
//                userIds.add(userEntity.getUserId());
//                break;
//            case DEPARTMENT:
//                //本部门
//                depIdIn = getUserBelongDeptIdList(userEntity, true);
//                userIds = getDepUserIdList(corpid, depIdIn, viewPermission);
//                break;
//            case DEPARTMENT_RECURSION:
//                //本部门和下属部门
//                depIdIn = getManagementDepIdList(userEntity);
//                userIds = getDepUserIdList(corpid, depIdIn, viewPermission);
//                break;
//            case CUSTOM:
//                //自定义
//                List<Long> weakManageDepIdList = new ArrayList<>();
//                Set<String> userIdSet = new HashSet<>();
//                String supUserId = userEntity.getUserId();
//                param.put("supStaffId", supUserId);
//                param.put("corpid", corpid);
//                param.put("del", 0);
//                List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
//                depIdIn = new ArrayList<>();
//                for(WeakManageEntity weakManage : weakManageList){
//                    Integer type = weakManage.getType();
//                    if(type.equals(1)){
//                        userIdSet.add(weakManage.getSubStaffId());
//                    }else if(type.equals(2)){
//                        Long subDepId = weakManage.getSubDepId();
//                        if (subDepId != null) {
//                            depIdIn.add(subDepId);
//                        }
//                    }
//                }
//                if (depIdIn.size() > 0) {
//                    param.clear();
//                    param.put("corpid", corpid);
//                    param.put("del", 0);
//                    param.put("idIn", depIdIn);
//                    weakManageDepIdList = departmentModel.getDepIds(param);
//                }
//                if(!weakManageDepIdList.isEmpty()){
//                    List<String> tempUserIds = getDepUserIdList(corpid, weakManageDepIdList, viewPermission);
//                    userIdSet.addAll(tempUserIds);
//                }
//
//                userIds = new ArrayList<>(userIdSet);
//                break;
//            case ALL:
//                //全公司
//                param.put("corpid", corpid);
//                //viewPermission = 1，则包含离职员工、且包含隐藏员工
//                if (viewPermission != 1) {
//                    param.put("del", 0);
//                }
//                param.put("start", 0);
//                param.put("pageNum", BasicConstant.MAX_USER_COUNT);
//                userIds = getUserIds(param);
//                break;
//            default:
//                break;
//        }
//        String userId = userEntity.getUserId();
//        if (excludeOneSelf) {
//            userIds.remove(userId);
//        } else {
//            userIds.add(userId);
//        }
//        return new ArrayList<>(new HashSet<>(userIds));
//    }


    @Override
    public List<String> getDepUserIdList(String corpid, Collection<Long> depIdIn) {
        return getDepUserIdList(corpid, depIdIn, 0);
    }

    @Override
    public List<Map<String, Object>> getUserIdsJoinDeptGroup(String corpid, Collection<Long> depIdIn) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("depIdIn", depIdIn);
        return userDao.getUserIdsJoinDeptGroup(param);
    }

    /**
     * //返回userIds
     * 获取部门极其下属部门的员工userId --- 递归，不包含隐藏部门、不包含离职员工
     * @param depIdIn 部门id列表
     * @param corpid 公司corpid
     * @return 部门极其下属部门的员工 userId
     */
    @Override
    public List<String> getUserIdsRecursionDep(List<Long> depIdIn,String corpid){
        return getUserIdsRecursionDep(depIdIn, corpid, 0);
    }
    /**
     * //返回userIds
     * 获取部门极其下属部门的员工id --- 递归，不包含隐藏部门
     * @param depIdIn   部门id列表
     * @param corpid 公司corpid
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @return
     * @author cp.zhang
     * @time 2017-3-3 下午7:13:49
     */
    @Override
    public List<String> getUserIdsRecursionDep(List<Long> depIdIn,String corpid, int viewPermission){
        return getUserIdsRecursionDep(depIdIn, corpid, viewPermission, false);
    }

    /**
     * //返回userIds
     * 获取部门极其下属部门的员工id --- 递归
     *
     * @param depIdIn        部门id列表
     * @param corpid         公司corpid
     * @param viewPermission 0默认，不包含离职员工		1包含离职员工
     * @param showHidden     是否考虑隐藏部门（即del = 2的部门），true 显示，false 不显示
     * @return java.util.List<java.lang.String> 员工userIds
     * @author zcp
     * @date 2019/2/14 9:01
     * @version v1.0
     * @since v1.0
     */
    @Override
    public List<String> getUserIdsRecursionDep(List<Long> depIdIn, String corpid, int viewPermission, boolean showHidden) {
        List<Long> depIdSet = departmentModel.getSubDepIdList(corpid, depIdIn, showHidden);
        return getDepUserIdList(corpid, depIdSet, viewPermission);
    }

    /**
     * 该方法是对getUserBelongDeptIdList()方法的重构：增加了xbb内助理部门ids的获取
     * （1）获得用户所属部门id列表
     * （2）若managedDep为true：1.返回管理的部门ID[在该部门为管理员]，2.返回所有助理部门
     *
     * @param userEntity 登录员工
     * @param managedDep 若managedDep为true则返回管理的部门ID[在该部门为管理员]以及xbb内所有助理部门ids,若为false则返回所在部门的id列表
     * @return 部门ids
     * @since v3.21
     * @version v3.21
     * @author cp.zhang
     * 创建时间：2018-5-7 下午3:41:29
     * 修改时间：
     */
    @Override
    public List<Long> getUserManageDeptIdList(UserEntity userEntity, boolean managedDep) {
        // 员工不存在或不在可见范围内
        List<Long> retDepList = new ArrayList<>();
        if(userEntity == null) {
            return retDepList;
        }
        String corpid = userEntity.getCorpid();
        String userId = userEntity.getUserId();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("userId", userId);
        param.put("del", 0);
        if(managedDep){
            param.put("isLeader", 1);
        }
        List<UserDepartmentEntity> list = userDepartmentModel.findEntitys(param);
        for(UserDepartmentEntity userDepartmentEntity : list){
            retDepList.add(userDepartmentEntity.getDepartmentId());
        }
        if(managedDep){
            //获取在xbb内助理的部门
            param.clear();
            param.put("supStaffId", userId);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("type", 2);
            List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
            for(WeakManageEntity weakManage : weakManageList){
                Long subDepId = weakManage.getSubDepId();
                retDepList.add(subDepId);
            }
        }
        return retDepList;
    }

    /**
     * 获得用户所属部门id列表,若managedDep为true则返回管理的部门ID[在该部门为管理员]
     * @param userEntity userEntity
     * @param managedDep 若managedDep为true则返回管理的部门ID[在该部门为管理员],若为false则返回所在部门的id列表
     * @return 返回userEntity所管理/所在的部门
     * @author kaka
     * @date 2017年4月8日 下午1:56:49
     * 修改时间： 2017-07-12 20:11 by chy
     */
    @Override
    public List<Long> getUserBelongDeptIdList(UserEntity userEntity, boolean managedDep) {
        List<Long> retDepList = new ArrayList<>();
        // 员工不存在或不在可见范围内
        if(userEntity == null) {
            return retDepList;
        }
        return getUserBelongDeptIdList(userEntity.getCorpid(), userEntity.getUserId(), managedDep);
    }

    @Override
    public List<Long> getUserBelongDeptIdList(String corpid, String userId, boolean managedDep) {
        List<Long> retDepList = new ArrayList<>();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("userId", userId);
        param.put("del", 0);
        if(managedDep){
            param.put("isLeader", 1);
        }
        List<UserDepartmentEntity> list = userDepartmentModel.findEntitys(param);

        for(UserDepartmentEntity userDepartmentEntity : list){
            retDepList.add(userDepartmentEntity.getDepartmentId());
        }

        return retDepList;
    }

    /**
     * 获得用户所属部门名称列表
     *
     * @param corpid
     * @param userIdIn
     * @return 用户ID--部门名称
     * kaka
     * 2020年11月6日 下午1:56:49
     * 修改时间： 2020-11-12 20:11 by youli.chen
     */
    @Override
    public Map<String, String> getUserBelongDeptNameMap(String corpid, List<String> userIdIn) {
        Map<String, String> userBelongDeptNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("userIdIn", userIdIn);
        param.put("del", 0);
        List<UserDepartmentEntity> list = userDepartmentModel.findEntitys(param);

        // 员工对应的多个部门id
        Map<String, List<Long>> userDepMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        List<Long> retDepList = new ArrayList<>();
        for(UserDepartmentEntity userDepartmentEntity : list){
            String userId = userDepartmentEntity.getUserId();
            Long depId = userDepartmentEntity.getDepartmentId();

            retDepList.add(depId);

            List<Long> deptList = userDepMap.getOrDefault(userId, new ArrayList<>());
            deptList.add(depId);
            userDepMap.put(userId, deptList);
        }

        Map<Long, String> depIdNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 获取部门
        List<DepartmentEntity> allDepList = departmentModel.getByDepIdIn(corpid, retDepList);
        for (DepartmentEntity department : allDepList) {
            depIdNameMap.put(department.getId(), department.getName());
        }

        Iterator iterator = userDepMap.keySet().iterator();
        while(iterator.hasNext()) {
            String userId = iterator.next().toString();
            List<String> departmentNameList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> departmentIdList = userDepMap.get(userId);
            for(Long departmentId : departmentIdList){
                String departmentName = depIdNameMap.get(departmentId);
                departmentNameList.add(departmentName);
            }
            String nameStr = StringUtils.join(departmentNameList, "，");
            userBelongDeptNameMap.put(userId, nameStr);
        }
        return userBelongDeptNameMap;
    }

    @Override
    public Map<Long, Set<String>> getDepIdUserIdsMap(List<UserEntity> userList) {
        if (userList == null) {
            return new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        }
        //部门id---该部门员工id list
        Map<Long, Set<String>> depIdUserIdsMap = new HashMap<>(userList.size());
        for(UserEntity userEntity : userList){
            String depIdStr = userEntity.getDepartment();
            List<Long> depIdList = null;
            try {
                depIdList = JSONArray.parseArray(depIdStr, Long.class);
            } catch (Exception e) {
            }
            if (depIdList == null) {
                continue;
            }
            String userId = userEntity.getUserId();
            for (Long depId : depIdList) {
                Set<String> userIds = depIdUserIdsMap.get(depId);
                if (userIds == null) {
                    userIds = new HashSet<>();
                }
                userIds.add(userId);
                depIdUserIdsMap.put(depId, userIds);
            }
        }
        return depIdUserIdsMap;
    }

    @Override
    public Integer updateAllVisibleByCorpId(String corpid, Integer isVisible) {
        Integer del = 0;
        if(isVisible.equals(1)) {
            del = 0;
        } else {
            del = 2;
        }
        return userDao.updateAllVisibleByCorpId(corpid, isVisible, del);
    }

    @Override
    public Integer updateVisibleByCorpIdAndUserIdNotIn(String corpid, Integer isVisible, List<String> userIdNotIn) {
        Integer del = 0;
        if(isVisible.equals(1)) {
            del = 0;
        } else {
            del = 2;
        }
        return userDao.updateVisibleByCorpIdAndUserIdNotIn(corpid, isVisible, userIdNotIn, del);
    }

    @Override
    public Integer clearUnauthUserByUpdateTime(String corpid, Integer updateTime) {
        return userDao.clearUnauthUserByUpdateTime(corpid, updateTime);
    }

    @Override
    public List<Long> getUserAssistDepIdList(String corpid, String userId) {
        List<Long> assistDepIdList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(16);
        param.put("supStaffId", userId);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("type", 2);
        List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
        for(WeakManageEntity weakManage : weakManageList){
            Long subDepId = weakManage.getSubDepId();
            assistDepIdList.add(subDepId);
        }
        return assistDepIdList;
    }

    @Override
    public List<String> getUserAssistUserIdList(String corpid, String userId) {
        List<String> assistUserIdList = new ArrayList<>();
        Map<String, Object> param = new HashMap<>(16);
        param.put("supStaffId", userId);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("type", 1);
        List<WeakManageEntity> weakManageList = weakManageModel.findEntitys(param);
        for(WeakManageEntity weakManage : weakManageList){
            String subUserId = weakManage.getSubStaffId();
            assistUserIdList.add(subUserId);
        }
        return assistUserIdList;
    }

    @Override
    public Integer deleteByCorpId(String corpid) {
        return userDao.deleteByCorpId(corpid);
    }


    //==================== private method ====================

    /**
     * 获取userEntity管理的所有部门的部门id列表（不考虑隐藏部门逻辑）
     * @param userEntity userEntity
     * @return userEntity管理的所有部门的部门id列表（不考虑隐藏部门逻辑）
     */
    private List<Long> getManagementDepIdList(UserEntity userEntity){
        // 员工管理的部门
        List<Long> depIdIn = getUserBelongDeptIdList(userEntity, true);
        // 通过router获取递归部门id列表
        return departmentModel.getSubDepIdList(userEntity.getCorpid(), depIdIn);
    }

    @Override
    public List<String> getUserIdsByRoles(String corpid, List<Integer> roleIdList) {
        Set<String> userIdSet = new HashSet<>();
        Map<String,Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("roleIdIn", roleIdList);
        List<String> userIds = getUserIds(param);
        userIdSet.addAll(userIds);
        return new ArrayList<>(userIdSet);
    }

    @Override
    public List<UserEntity> getByUserIdIn(String corpid, Collection<String> userIdIn) {
        return getByUserIdIn(corpid, userIdIn, true);
    }

    @Override
    public List<UserEntity> getByUserIdIn(String corpid, Collection<String> userIdIn, boolean ignoreDel) {
        if(Objects.isNull(userIdIn) || userIdIn.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("userIdIn", userIdIn);
        if (ignoreDel) {
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        }
        List<UserEntity> userList = findEntitys(param);

        // 对拥有相同 UserId 的用户队列进行排重
        Set<String> userIdSet = new HashSet<>();
        Iterator<UserEntity> userEntityIterator = userList.iterator();
        while (userEntityIterator.hasNext()) {
            UserEntity userEntity = userEntityIterator.next();
            if (userIdSet.contains(userEntity.getUserId())) {
                userEntityIterator.remove();
            } else {
                userIdSet.add(userEntity.getUserId());
            }
        }

        return userList;
    }

    @Override
    public List<UserEntity> getByUserIdIn(String corpid, Collection<String> userIdIn, Integer del) {
        if(Objects.isNull(userIdIn) || userIdIn.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("userIdIn", userIdIn);
        param.put(ParameterConstant.DEL, del);
        List<UserEntity> userList = findEntitys(param);

        // 对拥有相同 UserId 的用户队列进行排重
        Set<String> userIdSet = new HashSet<>();
        Iterator<UserEntity> userEntityIterator = userList.iterator();
        while (userEntityIterator.hasNext()) {
            UserEntity userEntity = userEntityIterator.next();
            if (userIdSet.contains(userEntity.getUserId())) {
                userEntityIterator.remove();
            } else {
                userIdSet.add(userEntity.getUserId());
            }
        }

        return userList;
    }

    @Override
    public boolean isBoss(UserEntity userEntity) {
        // 先判断userEntity中是否有bossByDataPermission属性
        Boolean isBossByDataPermission = userEntity.getBossByDataPermission();
        if (isBossByDataPermission == null) {
            isBossByDataPermission = isBoss(getDataPermission(userEntity, true));
            userEntity.setBossByDataPermission(isBossByDataPermission);
            return isBossByDataPermission;
        } else {
            return isBossByDataPermission;
        }
    }

    /**
     * 获取以用户id为key的用户名Map
     * @param corpid 公司id
     * @param userIds 用户id队列
     * @return Map<String, String> 以用户id为key的用户名Map
     *
     * @author 章华隽
     * 创建时间：2017/11/17 下午9:27
     * 修改时间：
     * @version
     * @since 3.14
     */
    @Override
    public Map<String, String> getUserIdNameMap(String corpid, Collection<String> userIds) {
        if (userIds == null || userIds.size() == 0) {
            return new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("userIdIn", userIds);
        params.put("start", 0);
        params.put("pageNum", userIds.size());
        params.put("columns", "user_id,name");
        List<UserEntity> userList = findEntitys(params);
        if (userList.size() == 0) {
            return new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        }
        Map<String, String> userIdNameMap = new HashMap<>(userList.size());
        for (UserEntity it : userList) {
            userIdNameMap.put(it.getUserId(), it.getName());
        }
        return userIdNameMap;
    }

    /**
     * 是否老板
     *
     * @param datePermission 权限范围
     * @return boolean
     */
    private boolean isBoss(Integer datePermission){
        return Objects.equals(datePermission, 5);
    }

    @Override
    public Map<String, String> getUserNameMap(String corpid, List<String> userList) {
        return getUserNameMap(corpid,userList,0);
    }
    @Override
    public Map<String, String> getUserNameMap(String corpid, List<String> userList, Integer leaveMarks) {
        if (userList.isEmpty()){
            return new HashMap<>();
        }
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("userIdIn",userList);
        map.put("columns","user_id,name");
        map.put(ParameterConstant.LEAVE_MARKS,leaveMarks);
        List<UserEntity> userEntityList = findEntitys(map);
        Map<String,String> userNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (UserEntity entity : userEntityList){
            userNameMap.put(entity.getUserId(),entity.getName());
        }
        return userNameMap;
    }

    @Override
    public Map<String, UserEntity> getUserEntityMap(String corpid, List<String> userList, Integer leaveMarks) {
        if (userList.isEmpty()){
            return new HashMap<>();
        }
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("userIdIn",userList);
        map.put(ParameterConstant.LEAVE_MARKS,leaveMarks);
        List<UserEntity> userEntityList = findEntitys(map);
        Map<String,UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (UserEntity entity : userEntityList){
            userMap.put(entity.getUserId(),entity);
        }
        return userMap;
    }

    /**
     *
     * @param corpid
     * @return
     */
    @Override
    public Map<String,String> getUserNameMapping(String corpid){
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("columns","user_id,name");
        List<UserEntity> userEntityList = findEntitys(map);
        Map<String,String> userNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (UserEntity entity : userEntityList){
            userNameMap.put(entity.getName(),entity.getUserId());
        }
        return userNameMap;
    }

    @Override
    public List<String> getPkUserIdIn(UserEntity userEntity, boolean pkLeave, Integer dataPermission) {
        String corpid = userEntity.getCorpid();
        String userId = userEntity.getUserId();
        // TODO 缓存机制
        List<String> userIdIn;

        if (isBoss(userEntity)) {
            Map<String, Object> userParam = new HashMap<>(16);
            userParam.put("corpid", corpid);
            //pkLeave为true，则包含离职员工、且包含隐藏员工
            if (!pkLeave) {
                userParam.put("del", DelEnum.NORMAL.getDel());
            }
            userParam.put("start", 0);
            userParam.put("pageNum", BasicConstant.MAX_USER_COUNT);

            userIdIn = getUserIds(userParam);
        } else {
            if (pkLeave) {
                userIdIn = getSubIdListByDataPermission(dataPermission, userId, corpid, BasicConstant.ONE, true);
            } else {
                userIdIn = getSubIdListByDataPermission(dataPermission, userId, corpid, BasicConstant.ZERO, true);
            }
            userIdIn.add(userId);
        }

        return userIdIn;
    }

    @Override
    public List<UserEntity> getPkUserList(UserEntity userEntity, List<String> userIdIn, boolean pkLeave) {
        List<UserEntity> userList = new ArrayList<>();
        if (userIdIn == null || userIdIn.size() == 0) {
            return userList;
        }
        String corpid = userEntity.getCorpid();
        Map<String, Object> tempMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        tempMap.put("corpid", corpid);
        //pkLeave为true，则包含离职员工、且包含隐藏员工
        if (!pkLeave) {
            tempMap.put("del", DelEnum.NORMAL.getDel());
        }
        tempMap.put("userIdIn", userIdIn);
        tempMap.put("start", 0);
        tempMap.put("pageNum", BasicConstant.MAX_USER_COUNT);
        userList = findEntitys(tempMap);
        return userList;
    }

    /**
     * 根据条件检索用户列表 拼音首字母排序
     *
     * @param param 检索条件
     * @return 符合条件的用户列表
     */
    @Override
    public List<UserEntityExt> findEntitysOrderByPinyin(Map<String, Object> param) {
        param.put("columns", PINYIN_COLUMNS);
        return userDao.findEntitysOrderByPinyin(param);
    }

    @Override
    public List<UserEntity> getByUserId(List<String> userIdList, String corpid) {
        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid",corpid);
        map.put("userIdIn",userIdList);
        map.put("del",0);
        return findEntitys(map);
    }

    @Override
    public UserEntity getByKeyIngoreDel(String key, String corpid) {
        return userDao.getByKey(key, corpid, null);
    }

    /**
     * 通过系统默认的角色获取用户
     *
     * @param corpid        公司id
     * @param roleIdList    角色id
     * @author GuoJun.HU
     * @since 3.19
     * 创建时间 2018/3/21 10:20
     */
    @Override
    public List<UserEntity> getUsersByRoleId(String corpid, List<Integer> roleIdList) {
        List<UserEntity> resultList = new ArrayList<>();
        if (roleIdList == null || roleIdList.isEmpty()) {
            return resultList;
        }

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        List<UserEntity> userList = findEntitys(param);

        for (UserEntity user : userList) {
            String roleIds = user.getRoleIds();
            if (StringUtil.isEmpty(roleIds)) {
                continue;
            }
            String[] roleArray = roleIds.split("\\|");
            for (String roleIdStr : roleArray) {
                Integer roleId = StringUtil.toInt(roleIdStr, -1);
                if (roleIdList.contains(roleId)) {
                    resultList.add(user);
                    break;
                }
            }
        }

        return resultList;
    }

    @Override
    public List<UserEntity> getUserNamesByIdIn(String corpId, List<String> userIdIn) {
        Map<String, Object> param = new HashMap<>(8);
        param.put(ParameterConstant.LEAVE_MARKS, BasicConstant.ONE);
        param.put(ParameterConstant.COLUMNS, "user_id, name");
        param.put("corpid", corpId);
        param.put("userIdIn", userIdIn);
        param.put("del", 0);
        return findEntitys(param);
    }

    @Override
    public List<UserEntity> getUserNamesByIdIn(String corpId, Collection<String> userIdIn, Integer delIgnore) {
        if (CollectionsUtil.isEmpty(userIdIn)) {
            return new ArrayList<>();
        }
        Map<String, Object> param = new HashMap<>(8);
        param.put(ParameterConstant.COLUMNS, "user_id, name");
        param.put("corpid", corpId);
        param.put("userIdIn", userIdIn);
        if (!Objects.equals(delIgnore, BasicConstant.ONE)) {
            // 排除已删除或已离职的用户
            param.put("negDel", 1);
        }
        if ( Objects.equals(delIgnore, BasicConstant.ONE) ) {
            param.put(ParameterConstant.LEAVE_MARKS, BasicConstant.ONE);
        }
        return findEntitys(param);
    }

    @Override
    public List<UserEntity> getUserNamesAllByIdIn(String corpId, List<String> userIdIn) {
        Map<String, Object> param = new HashMap<>(8);
        param.put(ParameterConstant.LEAVE_MARKS,BasicConstant.ONE);
        param.put(ParameterConstant.COLUMNS, "user_id, name");
        param.put("corpid", corpId);
        param.put("userIdIn", userIdIn);
        return findEntitys(param);
    }

    @Override
    public List<UserEntity> getUserWithRole(String corpid, Integer roleId) {
        return userDao.getUserWithRole(corpid, roleId);
    }

    @Override
    public Set<String> filterOutDepartingUser(Set<String> userIdList, String corpid) {
        Set<String> userIds = new HashSet<>();
        Map<String, Object> param = new HashMap<>(8);
        param.put(ParameterConstant.COLUMNS, "user_id");
        param.put("corpid", corpid);
        param.put("userIdIn", userIdList);
        param.put("del", 0);
        List<UserEntity> entitys = findEntitys(param);
        for (UserEntity userEntity : entitys) {
            userIds.add(userEntity.getUserId());
        }
        return userIds;
    }

    @Override
    public List<String> getManageUser(UserEntity userEntity) {
        String corpid = userEntity.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (userEntity.isOriAdmin()) {
            // 超管老板返回所有
            param.put("corpid", corpid);
            param.put("del", 0);
            return getUserIds(param);
        }
        String isLeaderInDepts = userEntity.getIsLeaderInDepts();
        if (StringUtil.isEmpty(isLeaderInDepts)) {
            // 兜底再查一次userEntity
            userEntity = getByKey(userEntity.getUserId(), corpid);
            if(Objects.nonNull(userEntity) && StringUtil.isNotEmpty(userEntity.getIsLeaderInDepts())){
                isLeaderInDepts = userEntity.getIsLeaderInDepts();
            } else {
                return new ArrayList<>();
            }
        }
        Map<Long, Boolean> isLeaderMap = JSON.parseObject(isLeaderInDepts,  new TypeReference<Map<Long,Boolean>>(){});
        Set<Long> deptIds = new HashSet<>();
        for(Map.Entry<Long, Boolean> isLeaderEntry : isLeaderMap.entrySet()) {
            if(isLeaderEntry.getValue()) {
                deptIds.add(isLeaderEntry.getKey());
            }
        }
        if (CollectionsUtil.isEmpty(deptIds)) {
            return new ArrayList<>();
        }
        return getDepUserIdList(corpid, deptIds);
    }

    @Override
    public List<String> getDelUserIds(String corpid) {
        List<String> delUserIdList;
        String value = paasRedisHelper.getValue(RedisPrefixConstant.DEL_USER_LIST,corpid);
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(ParameterConstant.CORPID, corpid);
        map.put(ParameterConstant.DEL, DelEnum.DELETE.getDel());
        if (Objects.isNull(value)) {
            delUserIdList = getUserIds(map);
            paasRedisHelper.setValue(RedisPrefixConstant.DEL_USER_LIST, corpid, JSONArray.toJSONString(delUserIdList), RedisTimeConstant.TEN_MINUTES);
        } else {
            try {
                delUserIdList = JSONArray.parseArray(value,String.class);
            } catch (Exception e) {
                delUserIdList = getUserIds(map);
                paasRedisHelper.setValue(RedisPrefixConstant.DEL_USER_LIST, corpid, JSONArray.toJSONString(delUserIdList), RedisTimeConstant.TEN_MINUTES);
            }
        }
        return delUserIdList;
    }

    @Override
    public UserEntity getAdminUser(String corpid) {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("active", 1);
        params.put("isAdmin", 1);
        params.put("limitNum", 1);
        return userDao.findEntitys(params).get(0);
    }

    @Override
    public UserVO getUserVO(String corpid, String userId, boolean userDetailFlag, boolean paasPermissionsFlag) throws XbbException {
        try {
            UserEntity user = getByKey(userId, corpid);
            //用户不存在
            if(user == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }

            //用户信息
            UserVO userVO = new UserVO();
            BeanUtil.copyProperties(user, userVO);

            //用户复杂数据
            if (userDetailFlag) {
                assembleUserVO(userVO, paasPermissionsFlag);
            }
            return userVO;
        } catch (XbbException e) {
            LOG.error("UserModel.getUserVO 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
        } catch (Exception e) {
            LOG.error("UserModel.getUserVO 执行出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 更新用户VO中的部门和角色数据
     * @param userVO 用户VO
     * @param paasPermissionsFlag 是否需要返回paas数据
     */
    @Override
    public void assembleUserVO(UserVO userVO, boolean paasPermissionsFlag) throws IllegalAccessException, InstantiationException, XbbException {
        if (userVO == null) {
            return;
        }
        // 最高数据权限
        int maxDataPermission = 1;
        Set<Integer> roleIdSet = new HashSet<>();
        Set<Long> departmentIdSet = new HashSet<>();
        formatRoleIdSet(userVO.getRoleIds(), roleIdSet);
        formatDepIdSet(userVO.getDepartment(), departmentIdSet);

        // 查询角色和部门
        List<RoleEntity> roleList = roleModel.getByRoleIdIn(userVO.getCorpid(), roleIdSet, paasPermissionsFlag);
        List<DepartmentEntity> depList = departmentModel.getByDepIdIn(userVO.getCorpid(), departmentIdSet);

        Set<RoleSimpleVO> roleSet = new HashSet<>();
        Set<DepartmentVO> depSet = new HashSet<>();
        Set<Integer> permissionIdsSet = new HashSet<>();
        Set<String> dynamicPermSet = new HashSet<>();
        String paasPermissions = null;
        // 数据权限封装
        Map<String, Integer> dataPermissionsDetail = new HashMap<>();
        Map<String, Object> params= new HashMap<>();
        params.put("aliasIn", ProPermissionAliasEnum.getFormPermissionAlias());
        List<ProPermissionEntity> proPermissionEntityList = proPermissionModel.findEntitys(params);
        Map<Integer, Integer> permissionIdAndBusinessTypeMap = new HashMap<>();
        // 管理中心中的组织权限id
        Integer organizationSetId = null;
        for (ProPermissionEntity entity : proPermissionEntityList) {
            String alias = entity.getAlias();
            ProPermissionAliasEnum proPermissionAliasEnum = ProPermissionAliasEnum.getByAlias(alias);
            if (!Objects.isNull(proPermissionAliasEnum)) {
                switch (proPermissionAliasEnum) {
                    case CUSTOMER_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        break;
                    case CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTACT.getCode());
                        break;
                    case CUSTOMER_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode());
                        break;
                    case COMMUNICATE_PLAN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.COMMUNICATE_PLAN.getCode());
                        break;
                    case SALES_OPPORTUNITY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode());
                        break;
                    case CONTRACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT.getCode());
                        break;
                    case SIGN_IN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SIGNIN.getCode());
                        break;
                    case WORK_REPORT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_REPORT.getCode());
                        break;
                    case QUOTATION:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.QUOTATION.getCode());
                        break;
                    case REFUND:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.REFUND.getCode());
                        break;
                    case SUPPLIER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER.getCode());
                        break;
                    case SUPPLIER_CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER_CONTACT.getCode());
                        break;
                    case SUPPLIER_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SUPPLIER_COMMUNICATE.getCode());
                        break;
                    case PURCHASE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE.getCode());
                        break;
                    case RETURNED_PURCHASE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
                        break;
                    case ASSEMBLE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ASSEMBLE.getCode());
                        break;
                    case INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_INSTOCK.getCode());
                        break;
                    case PURCHASE_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE_INSTOCK.getCode());
                        break;
                    case REFUND_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.REFUND_INSTOCK.getCode());
                        break;
                    case PRODUCTION_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode());
                        break;
                    case RETURNED_MATERIEL_INSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
                        break;
                    case OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_OUTSTOCK.getCode());
                        break;
                    case CONTRACT_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode());
                        break;
                    case RETURNED_PURCHASE_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode());
                        break;
                    case PRODUCTION_MATERIEL_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode());
                        break;
                    case WORK_ORDER_OUTSTOCK:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode());
                        break;
                    case INVENTORY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.INVENTORY.getCode());
                        break;
                    case TRANSFER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.TRANSFER.getCode());
                        break;
                    case WAREHOUSE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WAREHOUSE.getCode());
                        break;
                    case STOCK_SEARCH:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.STOCK_SEARCH.getCode());
                        break;
                    case BOM_BILL:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.BOM_BILL.getCode());
                        break;
                    case PRODUCTION_ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
                        break;
                    case PRODUCT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PRODUCT.getCode());
                        break;
                    case PAYMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT.getCode());
                        break;
                    case PAYMENT_SHEET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAYMENT_SHEET.getCode());
                        break;
                    case PAY_PLAN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAY_PLAN.getCode());
                        break;
                    case INVOICE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.INVOICE.getCode());
                        break;
                    case WORK_ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER.getCode());
                        break;
                    case ORGANIZATION_SET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SYSTEM.getCode());
                        organizationSetId = entity.getId();
                        break;
                    case PURCHASE_INVOICE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PURCHASE_INVOICE.getCode());
                        break;
                    case PAY_SHEET:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.PAY_SHEET.getCode());
                        break;
                    case MARKET_ACTIVITY:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKET_ACTIVITY.getCode());
                        break;
                    case CLUE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CLUE.getCode());
                        break;
                    case CREDIT_LIMIT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CREDIT_LIMIT.getCode());
                        break;
                    case CREDIT_FIXED_LIMIT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CREDIT_FIXED_LIMIT.getCode());
                        break;
                    case CREDIT_TEMPORARY_LIMIT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CREDIT_TEMPORARY_LIMIT.getCode());
                        break;
                    case CREDIT_CARD_BILL:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CREDIT_CARD_BILL.getCode());
                        break;
                    case DISTRIBUTOR_PROFILE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode());
                        break;
                    case DISTRIBUTOR_CONTACT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_CONTACT.getCode());
                        break;
                    case DISTRIBUTOR_COMMUNICATE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_COMMUNICATE.getCode());
                        break;
                    case ACCOUNT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_ACCOUNT.getCode());
                        break;
                    case ORDER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ORDER.getCode());
                        break;
                    case STATEMENTLIST:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CUSTOMER_STATEMENT_STATISTIC.getCode());
                        break;
                    case RETURN:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RETURN.getCode());
                        break;
                    case FUND_TRANSFER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.FUND_TRANSFER.getCode());
                        break;
                    case OTHER_INCOME:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_INCOME.getCode());
                        break;
                    case OTHER_EXPENSE:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.OTHER_EXPENSE.getCode());
                        break;
                    case MARKET_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKET_MANAGEMENT.getCode());
                        break;
                    case MARKETING_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.MARKETING_MANAGEMENT.getCode());
                        break;
                    case ORDER_CENTER:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.ORDER_CENTER.getCode());
                        break;
                    case DISTRIBUTOR_MANAGEMENT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode());
                        break;
                    case WORK_ORDER_V2:
                        // 工单
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.WORK_ORDER_V2.getCode());
                        break;
                    case RECEIPT_ORDER:
                        // 回执单
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.RECEIPT_ORDER.getCode());
                        break;
                    case SLA_RULE:
                        // sla规则
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SLA_RULE.getCode());
                        break;
                    case SLA_LOG:
                        // sla日志
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SLA_LOG.getCode());
                        break;
                    case SERVICE_PROJECT:
                        // 服务项目
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.SERVICE_PROJECT.getCode());
                        break;
                    case COMPETITOR:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.COMPETITOR.getCode());
                        break;
                    case CONTRACT_COMPARE_RESULT:
                        permissionIdAndBusinessTypeMap.put(entity.getId(), XbbRefTypeEnum.CONTRACT_COMPARE_RESULT.getCode());
                        break;
                    default:
                        break;

                }
            }
        }

        for (RoleEntity role : roleList) {
            RoleSimpleVO roleVO = new RoleSimpleVO();
            BeanUtil.copyProperties(role, roleVO);
            roleSet.add(roleVO);

            // 每个role的数据权限处理
            String dataPermissionDetailStr = role.getDataPermissionDetail();
            List<DataPermissionDetailPojo> dataPermissionDetailPojos = JSON.parseArray(dataPermissionDetailStr, DataPermissionDetailPojo.class);
            if (dataPermissionDetailPojos == null) {
                dataPermissionDetailPojos = new ArrayList<>();
            }
            // SaaS表单的数据权限map
            Map<Long, Integer> saasIdAndDataPermissionMap = new HashMap<>();
            // PaaS表单的数据权限map
            Map<Long, Integer> paasIdAndDataPermissionMap = new HashMap<>();
            for (DataPermissionDetailPojo pojo : dataPermissionDetailPojos) {
                List<DataPermissionsPojo> permissions = pojo.getPermissions();
                for (DataPermissionsPojo dataPermissionsPojo : permissions) {
                    if (Objects.equals(SaasMarkEnum.SAAS.getCode(), dataPermissionsPojo.getSaasMark())) {
                        saasIdAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    } else {
                        paasIdAndDataPermissionMap.put(dataPermissionsPojo.getId(), dataPermissionsPojo.getDataPermission());
                    }
                }
            }

            // SaaS数据权限处理，封到表单级
            Set<Integer> permissionIds = role.getPermissionIdsSet();
            boolean unContainsOrganization = false;
            if (!permissionIds.contains(organizationSetId)) {
                unContainsOrganization = true;
                permissionIds.add(organizationSetId);
            }
            for (Integer permissionId : permissionIds) {
                if (permissionIdAndBusinessTypeMap.containsKey(permissionId)) {
                    String key = SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + permissionIdAndBusinessTypeMap.get(permissionId).toString();
                    if (dataPermissionsDetail.containsKey(key)) {
                        Integer dataPermission = dataPermissionsDetail.get(key);
                        if (saasIdAndDataPermissionMap.containsKey(permissionId.longValue())) {
                            if (dataPermission < saasIdAndDataPermissionMap.getOrDefault(permissionId.longValue(), 1)) {
                                dataPermissionsDetail.put(key, saasIdAndDataPermissionMap.get(permissionId.longValue()));
                            }
                        } else {
                            if (dataPermission < role.getDataPermission()) {
                                dataPermissionsDetail.put(key, role.getDataPermission());
                            }
                        }
                    } else {
                        if (saasIdAndDataPermissionMap.containsKey(permissionId.longValue())) {
                            dataPermissionsDetail.put(key, saasIdAndDataPermissionMap.get(permissionId.longValue()));
                        } else {
                            dataPermissionsDetail.put(key, role.getDataPermission());
                        }
                    }
                }
            }

            // 追加 预收款：客户数据权限   预付款：供应商数据权限
            List<XbbRefTypeEnum> specialDataPermissionXbbRefTypes = Arrays.asList(XbbRefTypeEnum.CUSTOMER_MANAGEMENT, XbbRefTypeEnum.SUPPLIER);
            for (XbbRefTypeEnum type : specialDataPermissionXbbRefTypes) {
                Integer dataPermission = dataPermissionsDetail.getOrDefault(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + type.getCode(), DataPermissionEnum.SELF.getCode());
                if (Objects.equals(type, XbbRefTypeEnum.CUSTOMER_MANAGEMENT)) {
                    dataPermissionsDetail.put(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.PREPAYMENT_BALANCE.getCode(), dataPermission);
                }
                if (Objects.equals(type, XbbRefTypeEnum.SUPPLIER)) {
                    dataPermissionsDetail.put(SaasMarkEnum.SAAS.getCode() + StringConstant.UNDER_LINE + XbbRefTypeEnum.PREPAY_BALANCE.getCode(), dataPermission);
                }
            }

            // saas内paas表单的权限处理
            params.clear();
            params.put("columns", "id");
            params.put("corpid", userVO.getCorpid());
            params.put("aliasIn", Arrays.asList(SystemAppMenuEnum.CRM.getAlias(), SystemAppMenuEnum.JXC.getAlias(), SystemAppMenuEnum.PRODUCT.getAlias(), SystemAppMenuEnum.FUND_MANAGEMENT.getAlias()));
            params.put("del", 0);
            List<PaasAppEntity> paasAppEntities = paasAppDao.findEntitys(params);
            List<Long> appIds = new ArrayList<>();
            for (PaasAppEntity paasAppEntity : paasAppEntities) {
                appIds.add(paasAppEntity.getId());
            }

            params.clear();
            params.put("corpid", userVO.getCorpid());
            params.put("appIdIn", appIds);
            params.put("saasMark", SaasMarkEnum.PAAS.getCode());
            params.put("columns", "menu_id");
            params.put("del", 0);
            List<PaasFormEntity> paasFormEntities = paasFormDao.findEntity(params);
            for (PaasFormEntity paasFormEntity : paasFormEntities) {
                Long menuId = paasFormEntity.getMenuId();
                String key = SaasMarkEnum.PAAS.getCode() + StringConstant.UNDER_LINE + menuId;
                if (dataPermissionsDetail.containsKey(key)) {
                    Integer dataPermission = dataPermissionsDetail.get(key);
                    if (paasIdAndDataPermissionMap.containsKey(menuId)) {
                        if (dataPermission < paasIdAndDataPermissionMap.getOrDefault(menuId, 1)) {
                            dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(menuId));
                        }
                    } else {
                        if (dataPermission < role.getDataPermission()) {
                            dataPermissionsDetail.put(key, role.getDataPermission());
                        }
                    }
                } else {
                    if (paasIdAndDataPermissionMap.containsKey(menuId)) {
                        dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(menuId));
                    } else {
                        dataPermissionsDetail.put(key, role.getDataPermission());
                    }
                }
            }


            if (unContainsOrganization) {
                permissionIds.remove(organizationSetId);
            }

            // 数据权限PaaS部分
            List<AppPermissionPojo> appPerms = JSON.parseArray(role.getPaasPermissions(), AppPermissionPojo.class);
            if (Objects.nonNull(appPerms)) {
                for (AppPermissionPojo appPermissionPojo : appPerms) {
                    List<ModulePermissionPojo> modules = appPermissionPojo.getModules();
                    for (ModulePermissionPojo module : modules) {
                        String key = SaasMarkEnum.PAAS.getCode() + StringConstant.UNDER_LINE + module.getId();
                        if (dataPermissionsDetail.containsKey(key)) {
                            Integer dataPermission = dataPermissionsDetail.get(key);
                            if (paasIdAndDataPermissionMap.containsKey(module.getId())) {
                                if (dataPermission < paasIdAndDataPermissionMap.getOrDefault(module.getId(), 1)) {
                                    dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(module.getId()));
                                }
                            } else {
                                if (dataPermission < role.getDataPermission()) {
                                    dataPermissionsDetail.put(key, role.getDataPermission());
                                }
                            }
                        } else {
                            if (paasIdAndDataPermissionMap.containsKey(module.getId())) {
                                dataPermissionsDetail.put(key, paasIdAndDataPermissionMap.get(module.getId()));
                            } else {
                                dataPermissionsDetail.put(key, role.getDataPermission());
                            }
                        }
                    }
                }
            }

            // 计算最高dataPermission
            if (maxDataPermission < 5 && maxDataPermission < role.getDataPermission()) {
                maxDataPermission = role.getDataPermission();
            }

            // 权限处理
            String permissionStr = role.getPermissions();
            if (!StringUtil.isEmpty(permissionStr)){
                // 将role中已有权限统一并入permissionIdsSet
                permissionIdsSet.addAll(permissionIds);
            }

            // 计算 paasPermissions并集
            if (StringUtil.isEmpty(paasPermissions)) {
                paasPermissions = role.getPaasPermissions();
            } else {
                paasPermissions = SysProPermissionHelp.paasPermissionUnion(paasPermissions, role.getPaasPermissions());
            }
            if (role.isAdminOrBoss()) {
                dynamicPermSet.addAll(sysCloudCodeHelp.getCompanyDynamicPermissionSet(userVO.getCorpid()));
            } else {
                dynamicPermSet.addAll(SysCloudCodeHelp.getDynamicPermissionSet(role.getDynamicPermissions()));
            }
        }
        for (DepartmentEntity dep : depList) {
            DepartmentVO depVO = new DepartmentVO();
            BeanUtil.copyProperties(dep, depVO);
            depSet.add(depVO);
        }

        // 过滤未开启的应用/模块
        paasPermissions = filterPaasModule(userVO.getCorpid(), paasPermissions);
        filterSaasModule(userVO.getCorpid(), permissionIdsSet);

        // saas 权限
        if (permissionIdsSet.size() > 0) {
            List<String> perms = proPermissionModel.getByIdIn(permissionIdsSet);
            userVO.setPermSet(new HashSet<>(perms));
        }

        userVO.setDataPermissionDetail(dataPermissionsDetail);
        userVO.setPaasPermissions(paasPermissions);
        userVO.setDataPermission(maxDataPermission);
        userVO.setDynamicPermSet(dynamicPermSet);
        userVO.setRoleSet(roleSet);
        userVO.setDepSet(depSet);
    }

    @Override
    public UserVO getUserVoRoleAndDepartment(String corpid, String userId) {
        UserVO userVO = new UserVO();

        UserEntity userEntity = getByKeyIngoreDel(userId, corpid);

        if (Objects.isNull(userEntity)) {
            userVO.setUserId(userId);
            userVO.setCorpid(corpid);
            return userVO;
        }
        BeanUtil.copyProperties(userEntity, userVO);

        Set<Integer> roleIdSet = new HashSet<>();
        Set<Long> departmentIdSet = new HashSet<>();
        formatRoleIdSet(userEntity.getRoleIds(), roleIdSet);
        formatDepIdSet(userEntity.getDepartment(), departmentIdSet);

        // 查询角色和部门
        List<RoleEntity> roleList = roleModel.getByRoleIdIn(corpid, roleIdSet, false);
        List<DepartmentEntity> depList = departmentModel.getByDepIdIn(corpid, departmentIdSet);

        Set<RoleSimpleVO> roleSet = new HashSet<>();
        for (RoleEntity role : roleList) {
            RoleSimpleVO roleVO = new RoleSimpleVO();
            BeanUtil.copyProperties(role, roleVO);
            roleSet.add(roleVO);
        }
        Set<DepartmentVO> depSet = new HashSet<>();

        for (DepartmentEntity dep : depList) {
            DepartmentVO depVO = new DepartmentVO();
            BeanUtil.copyProperties(dep, depVO);
            depSet.add(depVO);
        }

        userVO.setRoleSet(roleSet);
        userVO.setDepSet(depSet);

        return userVO;
    }

    @Override
    public Integer updateBatch(List<UserEntity> userEntityList, String corpid) {
        return userDao.updateBatch(userEntityList, corpid);
    }

    /**
     * 将某个用户对应的角色id放入角色id集合 roleIdSet中
     * @param roleIds 某个用户表中的roleIds |1|2|格式
     * @param roleIdSet 角色id集合
     */
    private void formatRoleIdSet(String roleIds, Set<Integer> roleIdSet) {
        if (StringUtil.isEmpty(roleIds)) {
            // roleIds为空 异常数据可以记点日志
            return;
        }
        String[] roleIdArr = roleIds.split("\\|");
        for(String roleId : roleIdArr) {
            if(StringUtil.isEmpty(roleId)) {
                continue;
            }
            roleIdSet.add(Integer.valueOf(roleId));
        }
    }

    /**
     * 将某个用户对应的部门id放入部门id集合 departmentIdSet 中
     * @param department 某个用户所在的部门id数组，[1,2]格式
     * @param departmentIdSet 部门id集合
     */
    private void formatDepIdSet(String department, Set<Long> departmentIdSet) {
        if (StringUtil.isEmpty(department)) {
            // department为空 异常数据可以记点日志
            return;
        }
        JSONArray depArr = JSON.parseArray(department);
        if(depArr != null && depArr.size() > 0) {
            for (int i = 0; i < depArr.size(); i++) {
                try{
                    Long depId = depArr.getLong(i);
                    departmentIdSet.add(depId);
                } catch (JSONException je) {
                    LOG.error("department 字段格式错误", je);
                }
            }
        }
    }

    /**
     * 过滤未启用的 paas 应用和模块
     * @param corpid 公司id
     * @param paasPermissions paas权限
     * @return 返回修改后的paas权限
     */
    private String filterPaasModule(String corpid, String paasPermissions) {

        // 未启用的paas应用
        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("saasMark", 2);
        param.put("del", 0);
        param.put("enable", 0);
        List<PaasAppEntity> disableApps = paasAppDao.findEntitys(param);

        // 未启用的paas应用
        List<PaasMenuEntity> disableModules = paasMenuDao.findEntitys(param);
        if (disableApps.size() == 0 && disableModules.size() == 0) {
            return paasPermissions;
        }

        Set<Long> disableAppIds = new HashSet<>();
        for (PaasAppEntity appEntity : disableApps) {
            disableAppIds.add(appEntity.getId());
        }
        Set<Long> disableModuleIds = new HashSet<>();
        for (PaasMenuEntity menuEntity : disableModules) {
            disableModuleIds.add(menuEntity.getId());
        }

        List<AppPermissionPojo> appPerms = JSON.parseArray(paasPermissions, AppPermissionPojo.class);
        if (appPerms == null) {
            return paasPermissions;
        }
        Iterator<AppPermissionPojo> appPermsIterator = appPerms.iterator();
        while (appPermsIterator.hasNext()) {
            AppPermissionPojo appPermissionPojo = appPermsIterator.next();
            if (disableAppIds.contains(appPermissionPojo.getAppId())) {
                appPermsIterator.remove();
                continue;
            }
            List<ModulePermissionPojo> modulePerms = appPermissionPojo.getModules();
            if (modulePerms != null) {
                modulePerms.removeIf(modulePermissionPojo -> disableModuleIds.contains(modulePermissionPojo.getId()));
            }
        }

        return JSON.toJSONString(appPerms);
    }

    /**
     * 过滤未启用的saas应用和模块
     * 分为过滤app权限和模块权限
     * @param corpid 公司id
     * @param permissionIdsSet 该员工saas权限集合
     */
    private void filterSaasModule(String corpid, Set<Integer> permissionIdsSet) {
        // 关闭/没启用的应用 alias
        Set<String> disableAppSet = new HashSet<>();
        for (SystemAppMenuEnum appMenuEnum : SystemAppMenuEnum.values()) {
            // 注意，工单因为吴峰这边把应用和菜单的alias都设成了workOrder,所以要做一个人为替换，这样影响最小
            if (appMenuEnum.getAlias().equals(SystemAppMenuEnum.WORK_ORDER.getAlias())) {
                disableAppSet.add(ProPermissionAliasEnum.WORK_ORDER_APP.getAlias());
            } else {
                disableAppSet.add(appMenuEnum.getAlias());
            }
        }
        // 查出系统中已启用的应用，然后从未启用应用里面踢出
        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("saasMark", 1);
        param.put("del", 0);
        param.put("enable", 1);
        List<PaasAppEntity> enableApps = paasAppDao.findEntitys(param);

        for (PaasAppEntity app : enableApps) {
            //注意，工单因为吴峰这边把应用和菜单的alias都设成了workOrder,所以要做一个人为替换，这样影响最小
            if (app.getAlias().equals(SystemAppMenuEnum.WORK_ORDER.getAlias())) {
                disableAppSet.remove(ProPermissionAliasEnum.WORK_ORDER_APP.getAlias());
            } else {
                disableAppSet.remove(app.getAlias());
            }
        }

        // 找出所有未启用的模块
        Set<String> disableModuleSet = new HashSet<>();
        param.clear();
        param.put("corpid", corpid);
        param.put("saasMark", 1);
        param.put("del", 0);
        param.put("enable", 0);

        List<PaasMenuEntity> disableModules = paasMenuDao.findEntitys(param);
        for (PaasMenuEntity menu : disableModules) {
            disableModuleSet.add(menu.getAlias());
        }

        doFilterSaasModule(permissionIdsSet, disableAppSet, disableModuleSet);
    }

    /**
     * saas
     * 通过未启用的应用alias集合和未启用的菜单/模块alias集合过滤该用户的权限
     * @param permissionIdsSet 用户的saas权限集合
     * @param disableAppSet 未启用的saas应用alias集合
     * @param disableModuleSet 未启用的saas模块alias集合
     */
    private void doFilterSaasModule(Set<Integer> permissionIdsSet, Set<String> disableAppSet, Set<String> disableModuleSet) {
        Map<String, Object> param = new HashMap<>(16);
        // 获取disableAppSet 对应的proPermission列表, 并从permissionIdsSet中过滤对应的权限
        if (CollectionsUtil.isNotEmpty(disableAppSet)) {
            param.clear();
            param.put("enable", 1);
            param.put("del", 0);
            param.put("aliasIn", disableAppSet);
            List<Integer> appPermIds = proPermissionModel.findEntityIds(param);

            if (!appPermIds.isEmpty()) {
                // 拼装mysql正则值
                StringBuilder disAppSb = new StringBuilder();
                Iterator<Integer> appPermIdIter = appPermIds.iterator();
                while (appPermIdIter.hasNext()) {
                    Integer permId = appPermIdIter.next();
                    // 如果搜到的是332开头的，之前的方式会检索出1332或者2332等数据
                    disAppSb.append("(").append("^").append(permId).append(")");
                    if (appPermIdIter.hasNext()) {
                        disAppSb.append("|");
                    }
                }
                disAppSb.append("_+");
                param.clear();
                param.put("enable", 1);
                param.put("del", 0);
                param.put("routerReg", disAppSb.toString());

                List<Integer> disAppPermissionIds = proPermissionModel.findEntityIds(param);
                // 加上应用id
                disAppPermissionIds.addAll(appPermIds);
                permissionIdsSet.removeAll(disAppPermissionIds);
            }
        }

        // 获取disableAppSet 对应的proPermission列表, 并从permissionIdsSet中过滤对应的权限
        if (CollectionsUtil.isNotEmpty(disableModuleSet)) {
            param.clear();
            param.put("enable", 1);
            param.put("del", 0);
            param.put("aliasIn", disableModuleSet);
            List<Integer> modulePermIds = proPermissionModel.findEntityIds(param);

            if (!modulePermIds.isEmpty()) {
                param.clear();
                param.put("enable", 1);
                param.put("del", 0);
                param.put("parentIdIn", modulePermIds);

                List<Integer> disModulePermissionIds = proPermissionModel.findEntityIds(param);
                // 加上模块id
                disModulePermissionIds.addAll(modulePermIds);
                permissionIdsSet.removeAll(disModulePermissionIds);
            }
        }
    }

    @Override
    public UserFormPermissionVO getUserFormPermission(String corpid, String userId, Long appId, Long menuId) throws XbbException {
        UserFormPermissionVO formPermissionVO = new UserFormPermissionVO();
        ModulePermissionPojo formPermission = new ModulePermissionPojo();
        // 初始化该表单权限，后续通过实际该用户所具有的该表单权限进行覆盖
        PermissionTermsPojo permission = new PermissionTermsPojo();

        UserEntity user = getByKey(userId, corpid);
        if (user == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
        }

        PaasMenuEntity menu = paasMenuDao.getByKey(menuId, corpid);
        if (menu == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
        }
        formPermission.setId(menuId);
        formPermission.setType(menu.getType());

        Set<Integer> roleIdSet = new HashSet<>();
        formatRoleIdSet(user.getRoleIds(), roleIdSet);

        List<RoleEntity> roles = roleModel.getByRoleIdIn(corpid, roleIdSet, true);
        if (roles.size() > 0) {
            for (RoleEntity role : roles) {
                getMaxPermissionTerms(permission, role, appId, menuId);
            }
        }

        formPermission.setPermission(permission);
        formPermissionVO.setIsAdminOrBoss(user.isOriAdmin());
        formPermissionVO.setFormPermission(formPermission);
        return formPermissionVO;
    }

    /**
     * 通过已有 permissionTerms 和角色 role 计算对应该 appId 该 menuId 对应的最大 permissionTerms 权限
     * 执行完成后，最大权限会复写在 permissionTerms 中
     * @param permissionTerms 上次计算后的PermissionTermsPojo
     * @param role 角色实体
     * @param appId permissionTerms对应的appId
     * @param menuId permissionTerms对应的menuId
     */
    private void getMaxPermissionTerms(PermissionTermsPojo permissionTerms, RoleEntity role, Long appId, Long menuId) {
        if (permissionTerms == null || role == null || appId == null || menuId == null) {
            return;
        }
        // 解析appPermissionPojo
        ProPermissionHelp.getMaxPermissionTerms(permissionTerms, role.getPaasPermissions(), appId, menuId);
    }
}
